Register generic, where T is in a specific namespace

I currently have something like this:

new ContainerBuilder()
      .RegisterGeneric(typeof(MyFactory<>))
      .As(typeof(IMyFactory<>))
      .WithParameter("param", "abc")
      .SingleInstance();

      

I would like to limit myself to the above where T (in MyFactory<T>

) is in a specific namespace.

Is this possible with the help RegisterGeneric()

? If I use RegisterAssemblyTypes()

then I have to use Where(type => type.IsInNamespace("..."))

and register each type individually.

Is this the recommended approach?

+3


source to share


1 answer


There is no easy way to do this. By the way, you can use an event OnActivating

to replace an instance based on your type's namespace.

Let's say you have types in different namespaces:

public interface IFoo
{ }
namespace X
{
    public class FooX : IFoo { }
}
namespace Y
{
    public class FooY : IFoo { }
}

      

And 1 general Factory

and 2 specific:

public interface IFooFactory<TFoo>
    where TFoo : IFoo
{
    TFoo Create();
}

public class XFactory<TFoo> : IFooFactory<TFoo>
    where TFoo : IFoo
{
    public TFoo Create()
    {
        throw new NotImplementedException();
    }
}
public class YFactory<TFoo> : IFooFactory<TFoo>
    where TFoo : IFoo
{
    public TFoo Create()
    {
        throw new NotImplementedException();
    }
}
public class DefaultFactory<TFoo> : IFooFactory<TFoo>
    where TFoo : IFoo
{
    public TFoo Create()
    {
        throw new NotImplementedException();
    }
}

      

You can register your specific factories like this:



ContainerBuilder builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(XFactory<>))
       .Named("ProjectNamespace.X", typeof(IFooFactory<>));
builder.RegisterGeneric(typeof(YFactory<>))
       .Named("ProjectNamespace.Y", typeof(IFooFactory<>));

      

And your generic factory is like this:

builder.RegisterGeneric(typeof(DefaultFactory<>))
        .As(typeof(IFooFactory<>))
        .OnActivating(e =>
        {
            Type elementType = e.Instance.GetType().GetGenericArguments()[0];
            Type fooFactoryType = typeof(IFooFactory<>).MakeGenericType(elementType); 
            Service service = new KeyedService(elementType.Namespace, fooFactoryType);
            Object fooFactory = e.Context.ResolveOptionalService(service, e.Parameters);
            if (fooFactory != null)
            {
                e.ReplaceInstance(fooFactory);
            }
        });

      

Only the default factory is registered as IFooFactory<>

. If you try to resolve IFooFactory<X.FooX>

, then the OnActivating

event will replace the default factory instance and you getXFooFactory<X.FooX>

The main disadvantage of this is that a DefaultFactory<>

will be determined every time. This can be a problem if this registration depends on another or if it takes time to initialize.

+1


source







All Articles