【发布时间】:2018-06-24 13:32:06
【问题描述】:
我想使用程序集扫描器模式并使用另一个程序集的属性注册类
项目:AssemblyScanner
using System;
namespace AssemblyScanner
{
public class RegisterScope : Attribute
{
public RegisterScope()
{
}
}
}
项目:Domian.Service
namespace Domain.Service.Test
{
[RegisterScope]
public class CarService
{
}
}
项目:单元测试
using AssemblyScanner;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Domain.Service.Test;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Xunit;
namespace UnitTests
{
public class AssemblyScannerTests
{
[Fact]
public void AssemblyScannerTest()
{
var t = AssemblyScannerPattern().GetService<CarService>();
//AssemblyScannerPattern -> https://stackoverflow.com/questions/33811015/autofac-how-to-load-assemblies-that-are-referenced-but-not-directly-used
//Other Example -> https://www.codeproject.com/Articles/1201502/Dependency-Injection-in-ASP-NET-Web-API-using-Auto
}
public AutofacServiceProvider AssemblyScannerPattern()
{
var serviceCollection = new ServiceCollection();
ContainerBuilder builder = new ContainerBuilder();
string[] assemblyScanerPattern = new[] { @"Domain.Service*.dll" };
// Make sure process paths are sane...
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
// begin setup of autofac >>
// 1. Scan for assemblies containing autofac modules in the bin folder
List<Assembly> assemblies = new List<Assembly>();
assemblies.AddRange(
Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.dll", SearchOption.AllDirectories)
.Where(filename => assemblyScanerPattern.Any(pattern => Regex.IsMatch(filename, pattern)))
.Select(Assembly.LoadFrom)
);
foreach (var assembly in assemblies)
{
builder.RegisterAssemblyTypes(assembly)
.AsImplementedInterfaces();
}
foreach (var assembly in assemblies)
{
foreach (var attributeClass in assembly.ExportedTypes)
{
foreach (var registerScope in attributeClass.CustomAttributes.Where(s => s.AttributeType.Name.Contains("RegisterScope")))
{
var importedClassFromAssembly = GetInstance(attributeClass.Namespace + "." + attributeClass.Name);
//builder.RegisterType<importedClassFromAssembly.GetType>().As(importedClassFromAssembly);
}
}
}
var container = builder.Build();
var serviceProvider = new AutofacServiceProvider(container);
return serviceProvider;
}
public object GetInstance(string strFullyQualifiedName)
{
Type type = Type.GetType(strFullyQualifiedName);
if (type != null)
return Activator.CreateInstance(type);
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
type = asm.GetType(strFullyQualifiedName);
if (type != null)
return Activator.CreateInstance(type);
}
return null;
}
}
}
我找到了属性为“RegisterScope”的类,但我遇到了 builder.RegisterType 的问题
在这里我得到 null 但我想得到实例类
更新
当我写这篇文章时,我现在得到正确的对象会更好
builder.RegisterInstance(importedClassFromAssembly).As<CarService>();
但我想要这样的东西 - 错误
builder.RegisterInstance(importedClassFromAssembly).As<importedClassFromAssembly.GetType>();
我也试试这个(但这在 GetService() 中给了我 null;)
builder.RegisterInstance(importedClassFromAssembly).As<dynamic>();
当前代码存在最后一个小问题
using AssemblyScanner;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Domain.Service.Test;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Xunit;
namespace UnitTests
{
public class AssemblyScannerTests
{
[Fact]
public void AssemblyScannerTest()
{
var t = AssemblyScannerPattern().GetService<CarService>();
//AssemblyScannerPattern -> https://stackoverflow.com/questions/33811015/autofac-how-to-load-assemblies-that-are-referenced-but-not-directly-used
//Other Example -> https://www.codeproject.com/Articles/1201502/Dependency-Injection-in-ASP-NET-Web-API-using-Auto
}
public AutofacServiceProvider AssemblyScannerPattern()
{
var serviceCollection = new ServiceCollection();
ContainerBuilder builder = new ContainerBuilder();
string[] assemblyScanerPattern = new[] { @"Domain.Service*.dll" };
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
List<Assembly> assemblies = new List<Assembly>();
assemblies.AddRange(
Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.dll", SearchOption.AllDirectories)
.Where(filename => assemblyScanerPattern.Any(pattern => Regex.IsMatch(filename, pattern)))
.Select(Assembly.LoadFrom)
);
foreach (var assembly in assemblies)
{
foreach (var attributeClass in assembly.ExportedTypes)
{
if(attributeClass.CustomAttributes.Where(s => s.AttributeType.Name.Contains("RegisterScope")).Any())
{
var importedClassFromAssembly = GetInstance(attributeClass.FullName);
builder.RegisterInstance(importedClassFromAssembly).As<CarService>();
}
}
}
var container = builder.Build();
var serviceProvider = new AutofacServiceProvider(container);
return serviceProvider;
}
public object GetInstance(string strFullyQualifiedName)
{
Type type = Type.GetType(strFullyQualifiedName);
if (type != null)
return Activator.CreateInstance(type);
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
type = asm.GetType(strFullyQualifiedName);
if (type != null)
return Activator.CreateInstance(type);
}
return null;
}
}
}
【问题讨论】: