public IReadOnlyCollection<KeyValuePair<string, OperationInfo>> RegisterHandler(Assembly[] hostAssemblies)
{
if (Interlocked.Increment(ref alreadyRegistered) != 0) return new KeyValuePair<string, OperationInfo>[0];
var contractTypes = hostAssemblies
.SelectMany(x =>
{
try
{
return x.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
return ex.Types.Where(t => t != null);
}
})
.Where(x => typeof(LightNodeContract).IsAssignableFrom(x))
.Where(x => !x.IsAbstract());
Parallel.ForEach(contractTypes, classType =>
{
var className = classType.Name;
if (!classType.GetConstructors().Any(x => x.GetParameters().Length == 0))
{
throw new InvalidOperationException(string.Format("Type needs parameterless constructor, class:{0}", classType.FullName));
}
if (classType.GetCustomAttribute<IgnoreOperationAttribute>(true) != null) return; // ignore
foreach (var methodInfo in classType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
{
if (methodInfo.IsSpecialName && (methodInfo.Name.StartsWith("set_") || methodInfo.Name.StartsWith("get_"))) continue; // as property
if (methodInfo.GetCustomAttribute<IgnoreOperationAttribute>(true) != null) continue; // ignore
var methodName = methodInfo.Name;
// ignore default methods
if (methodName == "Equals"
|| methodName == "GetHashCode"
|| methodName == "GetType"
|| methodName == "ToString")
{
continue;
}
var sw = Stopwatch.StartNew();
// create handler
var handler = new OperationHandler(options, classType, methodInfo);
lock (handlers)
{
// fail duplicate entry
var path = new RequestPath(className, methodName);
if (handlers.ContainsKey(path))
{
throw new InvalidOperationException(string.Format("same class and method is not allowed, class:{0} method:{1}", className, methodName));
}
handlers.Add(path, handler);
}
sw.Stop();
options.Logger.RegisiterOperation(handler.ClassName, handler.MethodName, sw.Elapsed.TotalMilliseconds);
}
});
// return readonly operation info
return handlers.Select(x => new KeyValuePair<string, OperationInfo>(x.Key.ToString(), new OperationInfo(x.Value))).ToList().AsReadOnly();
}