Как использовать расширение соглашения со сложным инициированием (как: ToMethod)

пример расширения конвенции

kernel.Bind(x =>
{
    x.FromThisAssembly()
     .SelectAllClasses()
     .WithAttribute<SomeAttribute>()
     .BindBase();
});

И каждый тип, который я получаю, должен обеспечивать сложное инициирование этим методом.

 public static IPage GetInstance(Type type)
        {         
            MethodInfo method = typeof(PageService).GetMethod("Create");
            IPage page = (IPage)method.MakeGenericMethod(type).Invoke(null, new object[] { null });
            return page;
        }

2 ответа

Создать IBindingGenerator:

public class MyBindingGenerator : IBindingGenerator
{
    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(
        Type type,
        IBindingRoot bindingRoot)
    {
        yield return bindingRoot
            .Bind(type)
            .ToMethod(ctx => GetInstance(type));
    }

    public static object GetInstance(Type type)
    {
        MethodInfo method = typeof(PageService).GetMethod("Create");
        return method.MakeGenericMethod(type).Invoke(null, new object[] { null });
    }
}

и используйте его следующим образом:

kernel.Bind(x =>
{
    x.FromThisAssembly()
     .SelectAllClasses()
     .WithAttribute<SomeAttribute>()
     .BindWith<MyBindingGenerator>();
});

После некоторого поиска примеров я написал это решение. Я не знаю, является ли это лучшим решением, но в любом случае это работает для меня. Если кто-то улучшит мой код или напишет лучшую практику по моему вопросу, я буду благодарен:-)

UnitTest Где я хочу получить тип, который унаследован от IStepContext, которые имеют MarkAttribute

[TestClass]
public class Test
{
    private readonly IKernel _kernel = new StandardKernel();

    [TestInitialize]
    public void Startup()
    {           
        _kernel.Bind(a =>
        {
            a.FromThisAssembly()
                .SelectAllClasses()
                .InheritedFrom<IStepContext>()
                .WithAttribute<MarkAttribute>(x => x.Type == Inheritance.Derived).BindWith<SettingsBindGenerator>();
        });
    }
    [TestMethod]
    public void BaseClass()
    {
        BaseClass1 derived1 = _kernel.Get<BaseClass1>();
        Type res = derived1.WhoIAm(); //-- - > "BaseClass1"
        Assert.AreEqual(res, typeof (BaseClass1));
    }

    [TestMethod]
    public void DerivedClass()
    {
        IStepContextA derived = _kernel.Get<IStepContextA>();
        Type res = derived.WhoIAm(); //-- - > "DerivedClass"
        Assert.AreEqual(res, typeof (DerivedClass));
    }

    [TestMethod]
    public void DerivedClassA1()
    {
        IStepContext derived2 = _kernel.Get<BaseClassA>();
        Type res = derived2.WhoIAm(); //-- - > "DerivedClass"
        Assert.AreEqual(res, typeof (DerivedClassA1));
    }
}

Пользовательский BindGenerator

public class SettingsBindGenerator : IBindingGenerator
    {
        public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
        {
            Func<Type, IBindingWhenInNamedWithOrOnSyntax<object>> func =
                t => bindingRoot.Bind(t).ToMethod(ctx => GetInstance(ctx, type));


            var bindings = new List<IBindingWhenInNamedWithOrOnSyntax<object>>();

            // if type inherited from interface
            Type[] interfs = type.GetInterfaces();
            if (interfs.Length > 1)
            {
                // skip base interface (IStepContext)
                interfs = interfs.Take(interfs.Length - 1).ToArray();
                bindings = interfs.Select(x => func(x)).ToList();
            }

            // if type inherited from baseType
            Type baseType = type.BaseType;
            if (baseType != null)
            {
                bindings.Add(func(baseType));
                if (ShouldBeBound(baseType))
                {
                    var ancestor = baseType.BaseType;
                    while (ancestor != null && ShouldBeBound(ancestor))
                    {
                        bindings.Add(func(ancestor));
                        ancestor = ancestor.BaseType;
                    }
                }
            }
            return bindings;
        }

        private static bool ShouldBeBound(Type type)
        {
            return type.IsClass && type != typeof (object);
        }

        private object GetInstance(IContext ctx, Type type)
        {
            MethodInfo method = typeof(PageService).GetMethod("Create");
            IPage page = method.MakeGenericMethod(type).Invoke(null, new    object[] { null });        
            return page;   
        }
    }

Вспомогательные классы

 public class BaseClass : AbstractStepContext
    {
        public override Type WhoIAm()
        {
            return GetType();
        }
    }

    public class AbstractStepContext : IStepContext
    {
        public virtual Type WhoIAm()
        {
            return GetType();
        }
    }

 public class BaseClass1 : IBase
    {
        public virtual Type WhoIAm()
        {
            return GetType();
        }
    }
 [Mark(Inheritance.Base)]
    public class BaseClass1Derivied : BaseClass1
    {
        public override Type WhoIAm()
        {
            return GetType();
        }
    }

public class BaseClassA : AbstractStepContext
    {
        public virtual Type WhoIAm()
        {
            return GetType();
        }
    }

[Mark(Inheritance.Derived)]
    public class DerivedClass : IStepContextA
    {

        public Type WhoIAm()
        {
            return GetType();
        }

    }

[Mark(Inheritance.Derived)]
    public class DerivedClassA1 : BaseClassA
    {
        public override Type WhoIAm()
        {
            return GetType();
        }
    }

 public interface IStepContext
    {
        Type WhoIAm();
    }
    public interface IStepContextA : IStepContext
    {       
    }

public class MarkAttribute : Attribute
    {
        public Inheritance Type ;
        public MarkAttribute(Inheritance type)
        {
            Type = type;
        }
    }
Другие вопросы по тегам