2012-12-05 3 views
1

ASP.NET MVC 프로젝트에서 다음 코드 조각은 기본적으로 어셈블리 내의 특정 메서드에 인스턴스를 삽입합니다.인스턴스의 자동 주입 및 주입

그래서 응용 프로그램 루트에는이 인스턴스를 등록하고 마지막으로 주입을 처리하는 클래스가 있습니다.

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; 
    } 
} 

답변

0

, 내가 이해 당신은 당신이 마킹되어 무슨 뜻인지 correctly.if 클래스를 속성과의 종속성으로 사용하면 crea로 수행 할 수 있습니다.

public class DependencyAttribute : Attribute 
    { 
     public DependencyAttribute() 
     { 

     } 

     //The type of service the attributed class represents 
     public Type ServiceType { get; set; } 

     //Optional key to associate with the service 
     public string Key { get; set; } 

     public virtual void RegisterService(AttributeInfo<DependencyAttribute> attributeInfo, IContainer container) 
     { 
      Type serviceType = attributeInfo.Attribute.ServiceType ?? attributeInfo.DecoratedType; 
      Containerbuilder builder = new ContainerBuilder(); 
      builder.RegisterType(attributeInfo.DecoratedType).As(serviceType).Keyed(
             attributeInfo.Attribute.Key ?? attributeInfo.DecoratedType.FullName); 
      builder.Update(container) 
     } 
    } 

다음이 특성으로 표시된 모든 유형을 발견하고 이러한 특성의 RegisterService 메서드를 호출해야합니다 : 팅 정의 attribute.following는 이러한 속성을 구현하는 예입니다.

public class DependencyAttributeRegistrator 
    { 
     public DependencyAttributeRegistrator() 
     { 

     } 

     public IEnumerable<AttributeInfo<DependencyAttribute>> FindServices() 
     { 
      //replace this line with you'r own 
      var types = Assembly.GetExecutingAssembly().GetTypes(); 
      foreach (Type type in types) 
      { 
       var attributes = type.GetCustomAttributes(typeof(DependencyAttribute), false); 
       foreach (DependencyAttribute attribute in attributes) 
       { 
        yield return new AttributeInfo<DependencyAttribute> { Attribute = attribute, DecoratedType = type }; 
       } 
      } 
     } 

     public void RegisterServices(IEnumerable<AttributeInfo<DependencyAttribute>> services) 
     { 
      foreach (var info in services) 
      { 
       //replace following two line with you'r own global container 
       var builder = new ContainerBuilder(); 
       IContainer container = builder.Build(); 
       info.Attribute.RegisterService(info, container); 
      } 
     } 

    } 
+0

아니, 난 속성과 의존성 등의 클래스를 표시하고 싶지 않아, 나는 특정 방법으로 인스턴스를 주입, 내가 만든 인스턴스를 주입 Autofac을 사용하여 인스턴스를 등록하고 Autofac를 만들기 위해 원하는 I 내 경우에는 'ApplicationServiceProviderAttribute'특성으로 표시하십시오. –

+0

비슷한 코드로 예제를 제공 할 수 있습니까? –

+0

글쎄, 내 프로젝트에서 내가 가지고있는 현재의 솔루션을 게시 할 수있을 것 같아 도움이 될까요? –