在我正在開發的ASP.NET MVC項目中,我有下面這段代碼,它基本上將實例注入我的程序集中的特定方法。Autofac和實例注入
因此,在應用程序根目錄中,我有一個類來註冊像這樣的實例,並最終處理注入。
ApplicationServiceProvider serviceProvider = ApplicationServiceProvider.CreateDefaultProvider();
serviceProvider.RegisterInstance(GlobalConfiguration.Configuration);
serviceProvider.RegisterInstance(GlobalFilters.Filters);
serviceProvider.RegisterInstance(RouteTable.Routes);
serviceProvider.RegisterInstance(BundleTable.Bundles);
serviceProvider.Distribute();
現在,當我想從組件訪問這些情況下,我要創建一些處理程序(方法),並具有以下屬性'ApplicationServiceHandler就像在下面的例子中對它進行標記。
[ContractVerification(false)]
public static class RouteConfiguration
{
[ApplicationServiceHandler]
public static void Register(RouteCollection routes)
{
}
}
這是這是目前工作還算不錯的項目擴展層的一部分。
現在,我是新來的Autofac,我想知道我是否可以使用Autofac爲我完成這項工作,而不是使用我自己的實現(我在下面提供),可能效率較低,處理的案例少已經被Autofac覆蓋。
我注意到Autofac有一個RegisterInstance方法,但我不知道如何告訴它將實例注入用'ApplicationServiceHandler'屬性標記的方法,我不確定它甚至是正確的方法,但基於名稱它似乎是正確的。
非常感謝任何形式的幫助,謝謝。
編輯:下面是我使用的代碼,在我的項目中沒有Autofac的情況下實現這一點。
ApplicationServiceHandlerAttribute.cs
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ApplicationServiceHandlerAttribute : Attribute
{
}
ApplicationServiceHandler.cs
public sealed class ApplicationServiceHandler
{
private readonly MethodInfo _method;
private readonly object[] _args;
public ApplicationServiceHandler(MethodInfo method, object[] args)
{
Contract.Requires(method != null);
Contract.Requires(args != null);
_method = method;
_args = args;
}
public void Invoke()
{
_method.Invoke(null, _args);
}
[ContractInvariantMethod]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Required for code contracts.")]
private void ObjectInvariant()
{
Contract.Invariant(_method != null);
Contract.Invariant(_args != null);
}
}
ApplicationServiceProvider.cs
public sealed class ApplicationServiceProvider
{
private readonly IEnumerable<Assembly> _assemblies;
private readonly Dictionary<Type, object> _instances;
public ApplicationServiceProvider(IEnumerable<Assembly> assemblies)
{
Contract.Requires(assemblies != null);
_assemblies = assemblies;
_instances = new Dictionary<Type, object>();
}
public static ApplicationServiceProvider CreateDefaultProvider()
{
Contract.Ensures(Contract.Result<ApplicationServiceProvider>() != null);
return new ApplicationServiceProvider(PackageLoader.ReferencedAssemblies);
}
public void Distribute()
{
foreach (var handler in GetHandlers())
{
Contract.Assume(handler != null);
handler.Invoke();
}
}
public IEnumerable<ApplicationServiceHandler> GetHandlers()
{
Contract.Ensures(Contract.Result<IEnumerable<ApplicationServiceHandler>>() != null);
if (_instances.Count == 0)
{
yield break;
}
foreach (var asm in _assemblies)
{
IEnumerable<MethodInfo> methods = GetMethods(asm);
foreach (var method in methods)
{
ParameterInfo[] @params = method.GetParameters();
if (@params.Length > 0)
{
int instanceCount = 0;
object[] args = new object[@params.Length];
for (int i = 0; i < @params.Length; i++)
{
ParameterInfo param = @params[i];
var instance = GetInstance(param);
if (instance != null)
{
instanceCount++;
args[i] = instance;
}
}
if (instanceCount > 0)
{
yield return new ApplicationServiceHandler(method, args);
}
}
}
}
}
public bool RegisterInstance(object instance)
{
Contract.Requires(instance != null);
return AddInstance(instance);
}
private static ApplicationServiceHandlerAttribute GetApplicationServiceHandlerAttribute(MethodInfo method)
{
ApplicationServiceHandlerAttribute attribute = null;
try
{
attribute = method.GetCustomAttribute<ApplicationServiceHandlerAttribute>(false);
}
catch (TypeLoadException)
{
// We don't need to do anything here for now.
}
return attribute;
}
private static IEnumerable<Type> GetDefinedTypes(Assembly assembly)
{
Contract.Requires(assembly != null);
Contract.Ensures(Contract.Result<IEnumerable<Type>>() != null);
try
{
return assembly.DefinedTypes;
}
catch (ReflectionTypeLoadException ex)
{
return ex.Types.Where(type => type != null);
}
}
/// <summary>
/// Gets the methods that are marked with <see cref="ApplicationServiceHandlerAttribute"/> from the assembly.
/// </summary>
/// <remarks>
/// Eyal Shilony, 21/11/2012.
/// </remarks>
/// <param name="assembly">
/// The assembly.
/// </param>
/// <returns>
/// The methods that are marked with <see cref="ApplicationServiceHandlerAttribute"/> from the assembly.
/// </returns>
private static IEnumerable<MethodInfo> GetMethods(Assembly assembly)
{
Contract.Requires(assembly != null);
Contract.Ensures(Contract.Result<IEnumerable<MethodInfo>>() != null);
const TypeAttributes STATIC_TYPE_ATTRIBUTES = TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit;
var methods = (from type in GetDefinedTypes(assembly)
where type.Attributes == STATIC_TYPE_ATTRIBUTES
from method in type.GetMethods().AsParallel()
where GetApplicationServiceHandlerAttribute(method) != null
select method).ToArray();
return methods;
}
private bool AddInstance(object instance)
{
Type type = instance.GetType();
return AddInstance(type, instance);
}
private bool AddInstance(Type type, object instance)
{
if (!_instances.ContainsKey(type))
{
_instances.Add(type, instance);
return true;
}
return false;
}
private object GetInstance(ParameterInfo param)
{
object instance = null;
Type paramType = param.ParameterType;
if (_instances.ContainsKey(paramType))
{
instance = _instances[paramType];
}
else
{
foreach (var type in _instances.Keys.Where(type => type.IsSubclassOf(paramType)))
{
instance = _instances[type];
break;
}
}
return instance;
}
}
不,我不想要標記一個類爲依賴與屬性,我想注入,我做了一個實例,使用Autofac註冊實例,使Autofac注入實例具體方法,我標記一個屬性,在我的情況'ApplicationServiceProviderAttribute'。 –
你能提供一個類似代碼的例子嗎? –
嗯,我想我可以在我的項目中發佈當前的解決方案,對它有幫助嗎? –