From 1e91bac6d15dbf8ce7878f3f468e5452db161d0b Mon Sep 17 00:00:00 2001 From: yangxiaodong Date: Thu, 9 Feb 2017 18:07:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9C=8D=E5=8A=A1=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- global.json | 5 +- .../ConsistencyServer.cs | 1 + src/Cap.Consistency/ConsistencyBuilder.cs | 14 ++ .../Extensions/ReflectionExtensions.cs | 162 ++++++++++++++++++ src/Cap.Consistency/QMessageAttribute.cs | 14 ++ src/Cap.Consistency/QMessageFinder.cs | 48 ++++++ src/Cap.Consistency/QMessageMethodInfo.cs | 17 ++ src/Cap.Consistency/RouteTable.cs | 40 +++++ .../ServiceCollectionExtensions.cs | 4 + src/Cap.Consistency/project.json | 5 +- 10 files changed, 307 insertions(+), 3 deletions(-) create mode 100644 src/Cap.Consistency/Extensions/ReflectionExtensions.cs create mode 100644 src/Cap.Consistency/QMessageAttribute.cs create mode 100644 src/Cap.Consistency/QMessageFinder.cs create mode 100644 src/Cap.Consistency/QMessageMethodInfo.cs create mode 100644 src/Cap.Consistency/RouteTable.cs diff --git a/global.json b/global.json index 9a66d5e..b6dc362 100644 --- a/global.json +++ b/global.json @@ -1,3 +1,6 @@ { - "projects": [ "src", "test" ] + "projects": [ "src", "test" ], + "sdk": { + "version": "1.0.0-preview2-1-003177" + } } diff --git a/src/Cap.Consistency.Server/ConsistencyServer.cs b/src/Cap.Consistency.Server/ConsistencyServer.cs index 3eede87..29c858d 100644 --- a/src/Cap.Consistency.Server/ConsistencyServer.cs +++ b/src/Cap.Consistency.Server/ConsistencyServer.cs @@ -57,6 +57,7 @@ namespace Cap.Consistency.Server consumer.Start(); _logger.LogInformation("Started consumer..."); + } } } diff --git a/src/Cap.Consistency/ConsistencyBuilder.cs b/src/Cap.Consistency/ConsistencyBuilder.cs index 01f7508..ac68e23 100644 --- a/src/Cap.Consistency/ConsistencyBuilder.cs +++ b/src/Cap.Consistency/ConsistencyBuilder.cs @@ -1,6 +1,9 @@ using System; using System.Reflection; +using System.Collections.Concurrent; +using System.Linq; using Microsoft.Extensions.DependencyInjection; +using System.Collections.Generic; namespace Cap.Consistency { @@ -44,6 +47,17 @@ namespace Cap.Consistency return AddScoped(typeof(IConsistencyMessageStore<>).MakeGenericType(MessageType), typeof(T)); } + public virtual ConsistencyBuilder AddMessageMethodTable() { + var provider = Services.BuildServiceProvider(); + + var finder = provider.GetRequiredService(); + + finder.GetQMessageMethods(Services); + return null; + // Services.AddSingleton(serviceType, concreteType); + // return Add(typeof(IConsistencyMessageStore<>).MakeGenericType(MessageType), typeof(T)); + } + /// /// Adds a for the . /// diff --git a/src/Cap.Consistency/Extensions/ReflectionExtensions.cs b/src/Cap.Consistency/Extensions/ReflectionExtensions.cs new file mode 100644 index 0000000..773381c --- /dev/null +++ b/src/Cap.Consistency/Extensions/ReflectionExtensions.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Threading.Tasks; + +namespace Cap.Consistency.Extensions +{ + public static class ReflectionExtensions + { + public static Type MakeDefType(this TypeInfo byRefTypeInfo) + { + if (byRefTypeInfo == null) + { + throw new ArgumentNullException(nameof(byRefTypeInfo)); + } + if (!byRefTypeInfo.IsByRef) + { + throw new ArgumentException($"Type {byRefTypeInfo} is not passed by reference."); + } + + var assemblyQualifiedName = byRefTypeInfo.AssemblyQualifiedName; + var index = assemblyQualifiedName.IndexOf('&'); + assemblyQualifiedName = assemblyQualifiedName.Remove(index, 1); + + return byRefTypeInfo.Assembly.GetType(assemblyQualifiedName, true); + } + + public static bool CanInherited(this TypeInfo typeInfo) + { + if (typeInfo == null) + { + throw new ArgumentNullException(nameof(typeInfo)); + } + + if (!typeInfo.IsClass || typeInfo.IsSealed) + { + return false; + } + + if (typeInfo.IsNested) + { + return typeInfo.IsNestedPublic && typeInfo.DeclaringType.GetTypeInfo().IsPublic; + } + else + { + return typeInfo.IsPublic; + } + } + + internal static MethodInfo GetMethodBySign(this TypeInfo typeInfo, MethodInfo method) + { + if (method.IsGenericMethod) + { + foreach (var genericMethod in typeInfo.DeclaredMethods.Where(m => m.IsGenericMethod)) + { + if (method.ToString() == genericMethod.ToString()) + { + return genericMethod; + } + } + } + + return typeInfo.GetMethod(method.Name, method.GetParameterTypes()); + } + + public static Type[] GetParameterTypes(this MethodInfo method) + { + if (method == null) + { + throw new ArgumentNullException(nameof(method)); + } + return method.GetParameters().Select(parame => parame.ParameterType).ToArray(); + } + + public static bool IsPropertyBinding(this MethodInfo method) + { + if (method == null) + { + throw new ArgumentNullException(nameof(method)); + } + + return method.GetBindingProperty() != null; + } + + public static PropertyInfo GetBindingProperty(this MethodInfo method) + { + if (method == null) + { + throw new ArgumentNullException(nameof(method)); + } + + foreach (var property in method.DeclaringType.GetTypeInfo().DeclaredProperties) + { + if (property.CanRead && property.GetMethod == method) + { + return property; + } + + if (property.CanWrite && property.SetMethod == method) + { + return property; + } + } + + return null; + } + + public static MethodInfo GetMethod(Expression expression) + { + if (expression == null) + { + throw new ArgumentNullException(nameof(expression)); + } + var methodCallExpression = expression.Body as MethodCallExpression; + if (methodCallExpression == null) + { + throw new InvalidCastException("Cannot be converted to MethodCallExpression"); + } + return methodCallExpression.Method; + } + + public static MethodInfo GetMethod(string name) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + return typeof(T).GetTypeInfo().GetMethod(name); + } + + internal static MethodInfo ReacquisitionIfDeclaringTypeIsGenericTypeDefinition(this MethodInfo methodInfo, Type closedGenericType) + { + if (!methodInfo.DeclaringType.GetTypeInfo().IsGenericTypeDefinition) + { + return methodInfo; + } + + return closedGenericType.GetTypeInfo().GetMethod(methodInfo.Name, methodInfo.GetParameterTypes()); + } + + + + internal static string GetFullName(this MemberInfo member) + { + var declaringType = member.DeclaringType.GetTypeInfo(); + if (declaringType.IsInterface) + { + return $"{declaringType.Name}.{member.Name}".Replace('+', '.'); + } + return member.Name; + } + + internal static bool IsReturnTask(this MethodInfo methodInfo) + { + return typeof(Task).GetTypeInfo().IsAssignableFrom(methodInfo.ReturnType.GetTypeInfo()); + } + + } +} diff --git a/src/Cap.Consistency/QMessageAttribute.cs b/src/Cap.Consistency/QMessageAttribute.cs new file mode 100644 index 0000000..f9e63a8 --- /dev/null +++ b/src/Cap.Consistency/QMessageAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace Cap.Consistency +{ + [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)] + sealed class QMessageAttribute : Attribute + { + public QMessageAttribute(string messageName) { + MessageName = messageName; + } + + public string MessageName { get; private set; } + } +} diff --git a/src/Cap.Consistency/QMessageFinder.cs b/src/Cap.Consistency/QMessageFinder.cs new file mode 100644 index 0000000..3553313 --- /dev/null +++ b/src/Cap.Consistency/QMessageFinder.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using Cap.Consistency.Extensions; +using Microsoft.Extensions.DependencyInjection; + +namespace Cap.Consistency +{ + public class QMessageFinder + { + + public ConcurrentDictionary GetQMessageMethods(IServiceCollection serviceColloection) { + + if (serviceColloection == null) { + throw new ArgumentNullException(nameof(serviceColloection)); + } + + var qMessageTypes = new ConcurrentDictionary(); + + foreach (var serviceDescriptor in serviceColloection) { + + foreach (var method in serviceDescriptor.ServiceType.GetTypeInfo().DeclaredMethods) { + + var messageMethodInfo = new QMessageMethodInfo(); + + if (method.IsPropertyBinding()) { + continue; + } + + var qMessageAttr = method.GetCustomAttribute(); + if (qMessageAttr == null) { + continue; + } + + messageMethodInfo.MessageName = qMessageAttr.MessageName; + messageMethodInfo.ImplType = method.DeclaringType; + messageMethodInfo.MethodInfo = method; + + qMessageTypes.AddOrUpdate(qMessageAttr.MessageName, messageMethodInfo, (x, y) => y); + } + } + return qMessageTypes; + } + } +} diff --git a/src/Cap.Consistency/QMessageMethodInfo.cs b/src/Cap.Consistency/QMessageMethodInfo.cs new file mode 100644 index 0000000..7bd3068 --- /dev/null +++ b/src/Cap.Consistency/QMessageMethodInfo.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace Cap.Consistency +{ + public class QMessageMethodInfo + { + public MethodInfo MethodInfo { get; set; } + + public Type ImplType { get; set; } + + public string MessageName { get; set; } + } +} diff --git a/src/Cap.Consistency/RouteTable.cs b/src/Cap.Consistency/RouteTable.cs new file mode 100644 index 0000000..f327cf6 --- /dev/null +++ b/src/Cap.Consistency/RouteTable.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Cap.Consistency +{ + public class RouteTable : IReadOnlyList + { + + public RouteTable() { + + } + + public RouteTable(List messageMethods) { + QMessageMethods = messageMethods; + } + + public QMessageMethodInfo this[int index] { + get { + throw new NotImplementedException(); + } + } + + public int Count { + get { + throw new NotImplementedException(); + } + } + + public List QMessageMethods { get; set; } + + public IEnumerator GetEnumerator() { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() { + throw new NotImplementedException(); + } + } +} diff --git a/src/Cap.Consistency/ServiceCollectionExtensions.cs b/src/Cap.Consistency/ServiceCollectionExtensions.cs index 15c39cc..058fcc0 100644 --- a/src/Cap.Consistency/ServiceCollectionExtensions.cs +++ b/src/Cap.Consistency/ServiceCollectionExtensions.cs @@ -33,6 +33,10 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddScoped, ConsistencyMessageManager>(); + + services.AddSingleton(); + + if (setupAction != null) { services.Configure(setupAction); } diff --git a/src/Cap.Consistency/project.json b/src/Cap.Consistency/project.json index 72e93d3..57ee45f 100644 --- a/src/Cap.Consistency/project.json +++ b/src/Cap.Consistency/project.json @@ -1,11 +1,12 @@ -{ +{ "version": "1.0.0-*", "dependencies": { "Microsoft.AspNetCore.Http.Abstractions": "1.1.0-*", "Microsoft.Extensions.Options": "1.1.0-*", "Microsoft.Extensions.DependencyInjection.Abstractions": "1.1.0", "Microsoft.Extensions.Logging.Abstractions": "1.1.0-*", - "NETStandard.Library": "1.6.1" + "NETStandard.Library": "1.6.1", + "Microsoft.Extensions.DependencyInjection": "1.1.0" }, "frameworks": { "netstandard1.6": {