4

.net core中实现服务自动发现

 6 months ago
source link: https://www.cnblogs.com/TianFang/p/17865748.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

.net core中自带了依赖注入框架,asp.net core或worker框架下可以直接使用, 控制台程序可以通过加入Microsoft.Extensions.DependencyInjection程序包来支持。自带的di框架功能还行, 但是一个不方便的地方是没有提供服务自动发现、注册的接口,稍微大的程序都是需要通过反射自己写一个发现程序的。

今天网上找到了一个第三方实现的服务发现的库Scrutor,还比较好用, 示例如下:

var collection = new ServiceCollection(); collection.Scan(scan => scan // We start out with all types in the assembly of ITransientService .FromAssemblyOf<ITransientService>() // AddClasses starts out with all public, non-abstract types in this assembly. // These types are then filtered by the delegate passed to the method. // In this case, we filter out only the classes that are assignable to ITransientService. .AddClasses(classes => classes.AssignableTo<ITransientService>()) // We then specify what type we want to register these classes as. // In this case, we want to register the types as all of its implemented interfaces. // So if a type implements 3 interfaces; A, B, C, we'd end up with three separate registrations. .AsImplementedInterfaces() // And lastly, we specify the lifetime of these registrations. .WithTransientLifetime() // Here we start again, with a new full set of classes from the assembly above. // This time, filtering out only the classes assignable to IScopedService. .AddClasses(classes => classes.AssignableTo<IScopedService>()) // Now, we just want to register these types as a single interface, IScopedService. .As<IScopedService>() // And again, just specify the lifetime. .WithScopedLifetime() // Generic interfaces are also supported too, e.g. public interface IOpenGeneric<T> .AddClasses(classes => classes.AssignableTo(typeof(IOpenGeneric<>))) .AsImplementedInterfaces() // And you scan generics with multiple type parameters too // e.g. public interface IQueryHandler<TQuery, TResult> .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>))) .AsImplementedInterfaces());

这个类本身是比较好用的,但是它仍需要手工制定程序集作为扫描范围。 这个程序集的范围并不是所有程序集,往往只有用户代码程序集, asp.net core程序内部是有这个功能的,例如它内部就能扫描所有用户程序集,生成ApiController,网上搜了一下,发现还是一个内部接口,不过可以通过反射来调用:

public static Assembly[] GetAssemblies() { var manager = new ApplicationPartManager(); var method = manager.GetType() .GetMethod("PopulateDefaultParts", BindingFlags.NonPublic | BindingFlags.Instance); //加载入口程序集的依赖项树中的所有非官方包的依赖程序集 var assembly = Assembly.GetEntryAssembly().FullName; method.Invoke(manager, new object[] { assembly }); return manager.ApplicationParts.OfType<AssemblyPart>().Select(i => i.Assembly).ToArray(); }

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK