Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 覆盖StructureMap 3中的自定义注册约定_C#_Generics_Registration_Ioc Container_Structuremap - Fatal编程技术网

C# 覆盖StructureMap 3中的自定义注册约定

C# 覆盖StructureMap 3中的自定义注册约定,c#,generics,registration,ioc-container,structuremap,C#,Generics,Registration,Ioc Container,Structuremap,我在最近的项目中使用了CQRS模式,并将structuremap3用作我的IoC容器,因此我定义了以下转换来解析每个BaseEntity类型的icommandhelders: public class InsertCommandRegistrationConvention : StructureMap.Graph.IRegistrationConvention { private static readonly Type _openHandlerInterfaceType =

我在最近的项目中使用了
CQRS
模式,并将
structuremap3
用作我的
IoC容器
,因此我定义了以下转换来解析每个
BaseEntity
类型的
icommandhelders

 public class InsertCommandRegistrationConvention 
    : StructureMap.Graph.IRegistrationConvention
{
    private static readonly Type _openHandlerInterfaceType = typeof(ICommandHandler<>);
    private static readonly Type _openInsertCommandType = typeof(InsertCommandParameter<>);
    private static readonly Type _openInsertCommandHandlerType = typeof(InsertCommandHandler<>);

    public void Process(Type type, Registry registry)
    {
        if (!type.IsAbstract && typeof(BaseEntity).IsAssignableFrom(type) &&
            type.GetInterfaces().Any(x => x.IsGenericType && 
                x.GetGenericTypeDefinition() == typeof(IAggregateRoot<>)))
        {
            Type closedInsertCommandType = _openInsertCommandType.MakeGenericType(type);
            Type closedInsertCommandHandlerType =
                _openInsertCommandHandlerType.MakeGenericType(type);

            Type insertclosedHandlerInterfaceType =
                _openHandlerInterfaceType.MakeGenericType(closedInsertCommandType);
            registry.For(insertclosedHandlerInterfaceType)
                .Use(closedInsertCommandHandlerType);
        }
    }
}
公共类InsertCommandRegistrationConvention
:StructureMap.Graph.i注册转换
{
私有静态只读类型_openHandlerInterfaceType=typeof(ICommandHandler);
私有静态只读类型_openInsertCommandType=typeof(InsertCommandParameter);
私有静态只读类型_openInsertCommandHandlerType=typeof(InsertCommandHandler);
公共作废进程(类型、注册表)
{
如果(!type.isastract&&typeof(BaseEntity).IsAssignableFrom(type)&&
type.GetInterfaces().Any(x=>x.IsGenericType&&
x、 GetGenericTypeDefinition()
{
类型closedInsertCommandType=\u openInsertCommandType.MakeGenericType(类型);
类型closedInsertCommandHandlerType=
_openInsertCommandHandlerType.MakeGenericType(类型);
类型insertclosedHandlerInterfaceType=
_openHandlerInterfaceType.MakeGenericType(closedInsertCommandType);
注册表.For(insertclosedHandlerInterfaceType)
.使用(closedInsertCommandHandlerType);
}
}
}
并在我的CompositionRoot中使用它:

public static class ApplicationConfiguration
{
    public static IContainer Initialize()
    {
        ObjectFactory.Initialize(x =>
        {
            x.Scan(s =>
            {
                s.TheCallingAssembly();
                s.WithDefaultConventions();
                s.Convention<InsertCommandRegistrationConvention>();
            });
        });

        return ObjectFactory.Container;
    }
}
公共静态类应用程序配置
{
公共静态IContainer初始化()
{
ObjectFactory.Initialize(x=>
{
x、 扫描(s=>
{
s、 装配件();
s、 使用默认约定();
s、 公约();
});
});
返回ObjectFactory.Container;
}
}
因此,对于每个my实体,它都会注册相应的
insertCommand处理程序
,例如它会注册

ICommandHandler

有时我需要为某些实体注册自定义的
InsertCommandHandler
s,例如
Product
我想为
ICommandHandler
注册非通用的
InsertProductCustomCommandHandler
类,而不是
InsertCommandHandler
(换句话说,我想覆盖
InsertCommendRegistrationConvention


使用Structuremap 3,我如何才能做到这一点?

您可以使用方法
IContainer.Configure()
-通过
Configure()
方法,您可以向现有的
容器或
ObjectFactory
添加其他配置

我已经简化了您的抽象,以实际证明这一点:

public abstract class BaseEntity { }
public interface ICommandHandler<T> { }
public class ClassA : BaseEntity { }
public class ClassB : BaseEntity { }
public class ClassC : BaseEntity { }
public class ClassD : BaseEntity { }
public class InsertCommandHandler<T> : ICommandHandler<T> { }
public class SpecialInsertDCommandHandler : ICommandHandler<ClassD> { }
此测试表明,配置了
InsertCommandRegistrationConvention
的容器将为所有4个测试类
ClassA
返回通用
InsertCommandHandler
,以
ClassD

[Test]
public void Handle_Initialize_RegistersClassesAToDToReturnInsertCommandHandler()
{
    var container = ApplicationConfiguration.Initialize();

    var resultA = container.GetInstance<ICommandHandler<ClassA>>();
    var resultB = container.GetInstance<ICommandHandler<ClassB>>();
    var resultC = container.GetInstance<ICommandHandler<ClassC>>();
    var resultD = container.GetInstance<ICommandHandler<ClassD>>();

    Assert.That(resultA.GetType() == typeof(InsertCommandHandler<ClassA>));
    Assert.That(resultB.GetType() == typeof(InsertCommandHandler<ClassB>));
    Assert.That(resultC.GetType() == typeof(InsertCommandHandler<ClassC>));
    Assert.That(resultD.GetType() == typeof(InsertCommandHandler<ClassD>));
}

您可以修改约定,例如“如果有特定的命令处理程序,请使用它。否则,请使用InsertCommandHandler。”

看起来是这样的(就像qujck,我简化了类):

公共类InsertCommandRegistrationConvention:IRegistrationConvention
{
私有静态只读类型_openHandlerInterfaceType=typeof(ICommandHandler);
私有静态只读类型_openInsertCommandHandlerType=typeof(InsertCommandHandler);
私有静态只读IList_customCommandHandlerTypes;
静态插入命令和注册转换()
{
_CustomCommandHandlerType=\u openInsertCommandHandlerType
装配
.导出类型
.其中(x=>!x.IsAbstract)
.其中(x=>!x.IsGenericType | | x.GetGenericTypeDefinition()!=typeof(InsertCommandHandler))
.Where(x=>x.GetInterfaces().Any(i=>i.IsGenericType&&i.GetGenericTypeDefinition()==typeof(ICommandHandler)))
.ToArray();
}
公共作废进程(类型、注册表)
{
如果(!type.isastract&&typeof(BaseEntity).IsAssignableFrom(type))
{
var insertclosedHandlerInterfaceType=\u openHandlerInterfaceType.MakeGenericType(类型);
var closedInsertCommandHandlerType=\u openInsertCommandHandlerType.MakeGenericType(类型);
//检查是否有任何实现ICommandHandler的类也不是InsertCommandHandler
var customHandler=_customCommandHandlerTypes.FirstOrDefault(t=>t.GetInterfaces().Any(i=>i==insertclosedHandlerInterfaceType));
注册表.For(insertclosedHandlerInterfaceType)
.使用(customHandler??closedInsertCommandHandlerType);
}
}
}
我使用的类:

public abstract class BaseEntity { }
public class Class1 : BaseEntity { }
public class Class2 : BaseEntity { }
public class SpecialClass :BaseEntity { }

public interface ICommandHandler<T> { }
public class InsertCommandHandler<T> : ICommandHandler<T> { }
public class SpecialClassInsertCommandHandler : ICommandHandler<SpecialClass> { }
公共抽象类BaseEntity{}
公共类Class1:BaseEntity{}
公共类Class2:BaseEntity{}
公共类SpecialClass:BaseEntity{}
公共接口ICommandHandler{}
公共类InsertCommandHandler:ICommandHandler{}
公共类SpecialClassInsertCommandHandler:ICommandHandler{}
通过的测试:

        Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class1>>(), Is.InstanceOf<InsertCommandHandler<Class1>>());
        Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class2>>(), Is.InstanceOf<InsertCommandHandler<Class2>>());
        Assert.That(ObjectFactory.GetInstance<ICommandHandler<SpecialClass>>(), Is.InstanceOf<SpecialClassInsertCommandHandler>());
Assert.That(ObjectFactory.GetInstance(),Is.InstanceOf());
Assert.That(ObjectFactory.GetInstance(),Is.InstanceOf());
Assert.That(ObjectFactory.GetInstance(),Is.InstanceOf());

优点是您修改了约定,而不是避免将其用于某些项目。如果您的逻辑需要更改,这会使所有内容保持在一个位置。

我使用了
container.Configure()
,但当我运行
WhatDoIHave()时
,它显示了对于
ICommandHandler
structuremap使用
InsertCommandHandler
作为(默认)和自定义
InsertCalendarCommandHandler
(但不是默认)。Hi@Masoud-我的代码以另一种方式显示它们,这有点令人费解-您添加了自定义注册表吗
public class InsertCommandRegistrationConvention : IRegistrationConvention
{
    private static readonly Type _openHandlerInterfaceType = typeof (ICommandHandler<>);
    private static readonly Type _openInsertCommandHandlerType = typeof (InsertCommandHandler<>);
    private static readonly IList<Type> _customCommandHandlerTypes;

    static InsertCommandRegistrationConvention()
    {
        _customCommandHandlerTypes = _openInsertCommandHandlerType
            .Assembly
            .ExportedTypes
            .Where(x => !x.IsAbstract)
            .Where(x => !x.IsGenericType || x.GetGenericTypeDefinition() != typeof (InsertCommandHandler<>))
            .Where(x => x.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommandHandler<>)))
            .ToArray();
    }

    public void Process(Type type, Registry registry)
    {
        if (!type.IsAbstract && typeof (BaseEntity).IsAssignableFrom(type))
        {
            var insertclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(type);
            var closedInsertCommandHandlerType = _openInsertCommandHandlerType.MakeGenericType(type);

            // check for any classes that implement ICommandHandler<T> that are not also InsertCommandHandler<T>
            var customHandler = _customCommandHandlerTypes.FirstOrDefault(t => t.GetInterfaces().Any(i => i == insertclosedHandlerInterfaceType));

            registry.For(insertclosedHandlerInterfaceType)
                .Use(customHandler ?? closedInsertCommandHandlerType);
        }
    }
}
public abstract class BaseEntity { }
public class Class1 : BaseEntity { }
public class Class2 : BaseEntity { }
public class SpecialClass :BaseEntity { }

public interface ICommandHandler<T> { }
public class InsertCommandHandler<T> : ICommandHandler<T> { }
public class SpecialClassInsertCommandHandler : ICommandHandler<SpecialClass> { }
        Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class1>>(), Is.InstanceOf<InsertCommandHandler<Class1>>());
        Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class2>>(), Is.InstanceOf<InsertCommandHandler<Class2>>());
        Assert.That(ObjectFactory.GetInstance<ICommandHandler<SpecialClass>>(), Is.InstanceOf<SpecialClassInsertCommandHandler>());