ipjohnson / Grace

Grace is a feature rich dependency injection container library
MIT License
336 stars 33 forks source link

Autoexport all types by interface by specific key #205

Closed mcdis closed 5 years ago

mcdis commented 5 years ago

Hi!

Can you help me with this scenario... I want to scan all types in specific assembly and export all types which impl specific interface...but I want to export by key which defined thru attribute. And I want to export with the specific lifestyle.

[Foo("a")]
class A: IExportInterface    {}

[Foo("b")]
class B: IExportInterface    {}

// ... after apply some grace magick ...
container.Locate<IExportInterface>(withKey: "a") // Yeah, It`a instance of A
container.Locate<IExportInterface>(withKey: "b") // Yeah, It`a instance of B

Some optimize and degree of freedom requirements:

ExportAssemblyContaining?

I can suggest some export method like:

_.ExportAssemblyContaining<IHofChangeProcessor>().ByKey(_type=>_type.GetTypeInfo().GetCustomAttribute<FooAttribute>().Name).Lifestyle.Singleton();

_.ExportAssemblyContaining<IHofChangeProcessor>(typeof(Anchor).Assembly).ByKey(_type=>_type.GetTypeInfo().GetCustomAttribute<FooAttribute>().Name).Lifestyle.Singleton();
mcdis commented 5 years ago

Can(How) I use interface IExportKeyedTypeAttribute?

mcdis commented 5 years ago

Tried this code and looks like it works...

container.Configure(_ =>
{
   _.ExportAssemblyContaining<IHofChangeProcessor>()
   .Where(_t => typeof(IHofChangeProcessor).IsAssignableFrom(_t))
   .ByInterface<IHofChangeProcessor>()
   .ExportAttributedTypes();
});
// ...
   [Singleton]
   [HofChangeProcessorType("create-competition")]
  public class CreateCompetitionHofProc : HofChangeProcessor<CreateCompetitionHofProcSettings> {}
// ..
   public class HofChangeProcessorTypeAttribute : Attribute, IExportKeyedTypeAttribute
   {
      public HofChangeProcessorTypeAttribute(string _type)
      {
         Type = _type;
      }
      public string Type { get; }
      public Tuple<Type, object> ProvideKey(Type _attributedType)
      {
         return new Tuple<Type, object>(typeof(IHofChangeProcessor), _attributedType.GetTypeInfo().GetCustomAttribute<HofChangeProcessorTypeAttribute>().Type.ToLower());
      }
   }
ipjohnson commented 5 years ago

Hi @mcdis

I’ve been away for the weekend but I’ll take a look this evening and put something together.

mcdis commented 5 years ago

I feel that there are some excessive descriptions. I think that add ability to provide key provider factory method during export is good choice. And we can combine type that identify assembly with export type.

_scope
.ExportAssemblyContaining<IdentifyAssemblyTypeD,IdentifyAssemblyTypeE,IdentifyAssemblyTypeF>() // multiply assemblies
.ByInterface<IFoo>() // .Where(_t => typeof(IFoo).IsAssignableFrom(_t)).ByInterface<IFoo>()
.ByKey(_type=>SelectKey(_type)) // factory selection method
.Lifestyle.Singleton()

Or some extra method OfInterface<IFoo>() ~ .Where(_t => typeof(IFoo).IsAssignableFrom(_t)).ByInterface<IFoo>()

ipjohnson commented 5 years ago

Hi @mcdis

I hesitate to add an ExportAssemblyContaining<T, T2, T3>() , I'd be open to something like ExportAssmbliesContaining(params Type[] types) that way there is only one new extension to cover all cases.

There is already a ByKeyedTypes method that lets you export a set by keyed types. I think an extension method like this would be what you want.

        public static IExportTypeSetConfiguration ByKeyed<T>(this IExportTypeSetConfiguration configuration, Func<Type, object> keyFunc)
        {
            configuration.ByKeyedTypes(type =>
            {
                if (typeof(T).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
                {
                    var key = keyFunc(type);

                    if(key != null)
                    {
                        return new[] { new Tuple<Type, object>(type, key) }; 
                    }

                    return null;
                }

                return null;
            });

            return configuration;
        }
mcdis commented 5 years ago

Hi @ipjohnson, That extension looks good!

ipjohnson commented 5 years ago

I'll look at putting this into a preview release in the next week. Did you want the extension ExportAssmbliesContaining(typeof(ClassA), typeof(ClassB))?

ipjohnson commented 5 years ago

I'm going to close this out as it will be released in 7.0