Unity 不使用配置文件解析嵌套的通用参数,而是使用 UnityContainer 解析
Unity not resolve nested generic arguments using the configuration file, but resolve using UnityContainer
我正在尝试从文件 Unity.config 加载 Unity 配置。在接口的实现中使用了通用参数
我的配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="TestUnityGeneric" />
<namespace name="TestUnityGeneric"/>
<container name="Entity">
<register type="IEventBus`2[IEvent`1[long],long]" mapTo="TestEventBus`2[IEvent`1[long],long]"></register>
<register type="ISender" mapTo="TestSender">
<constructor>
<param name="eventBus" dependencyType="IEventBus`2[IEvent`1[long], long]" />
</constructor>
</register>
</container>
</unity>
配置无效。 但下一个 C# 代码有效:
public interface IEvent<out Key>
{
Key SourceId { get; }
}
public interface IEventBus<E, in Key>
where E : IEvent<Key>
{
void Publish(E @event);
}
public class TestEventBus<E, Key> : IEventBus<E, Key>
where E : IEvent<Key>
{
public void Publish(E @event)
{
Console.WriteLine("Message published!");
}
}
public interface ISender
{
void SendToBus(string message);
}
public class TestSender : ISender
{
private IEventBus<IEvent<long>, long> _bus { get; set; }
public TestSender(IEventBus<IEvent<long>,long> eventBus)
{
Console.WriteLine("Sender Initialized");
_bus = eventBus;
}
public void SendToBus(string message)
{
IEvent<long> env = new TestEvent
{
SourceId = 1,
Message = message
};
_bus.Publish(env);
}
}
public class TestEvent : IEvent<long>
{
public long SourceId { get; set; }
public string Message { get; set; }
}
class Program
{
static void Main(string[] args)
{
// It Is not worked: Exception: "GenericArguments violates the constraint of type paremeter "E""
IUnityContainer container = new UnityContainer().LoadConfiguration(ConfigurationManager.AppSettings["UnityContainer"]);
// This is worked
/*
IUnityContainer container = new UnityContainer();
IEventBus<IEvent<long>, long> bus = new TestEventBus<IEvent<long>, long>();
container.RegisterInstance<IEventBus<IEvent<long>, long>>(bus);
container.RegisterType<ISender, TestSender>(new TransientLifetimeManager(),
new InjectionConstructor(typeof(IEventBus<IEvent<long>, long>)));
*/
var sender = container.Resolve<ISender>();
sender.SendToBus("MyMessage");
Console.ReadKey();
}
}
所有项目代码:HERE
已解决
事实证明,Unity 不理解 Unity.config 文件中的嵌套泛型。解决方案:使用 Alias,并且 Alias One 不应使用其他别名。此配置 - 有效:
<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="TestUnityGeneric" />
<namespace name="TestUnityGeneric"/>
<alias alias="IEventLong" type="TestUnityGeneric.IEvent`1[System.Int64], TestUnityGeneric" />
<container name="Entity">
<register type="IEventBus`2[IEventLong,long]" mapTo="TestEventBus`2[IEventLong,long]"></register>
<register type="ISender" mapTo="TestSender">
<constructor>
<param name="eventBus" dependencyType="IEventBus`2[IEventLong, long]" />
</constructor>
</register>
</container>
</unity>
我正在尝试从文件 Unity.config 加载 Unity 配置。在接口的实现中使用了通用参数 我的配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="TestUnityGeneric" />
<namespace name="TestUnityGeneric"/>
<container name="Entity">
<register type="IEventBus`2[IEvent`1[long],long]" mapTo="TestEventBus`2[IEvent`1[long],long]"></register>
<register type="ISender" mapTo="TestSender">
<constructor>
<param name="eventBus" dependencyType="IEventBus`2[IEvent`1[long], long]" />
</constructor>
</register>
</container>
</unity>
配置无效。 但下一个 C# 代码有效:
public interface IEvent<out Key>
{
Key SourceId { get; }
}
public interface IEventBus<E, in Key>
where E : IEvent<Key>
{
void Publish(E @event);
}
public class TestEventBus<E, Key> : IEventBus<E, Key>
where E : IEvent<Key>
{
public void Publish(E @event)
{
Console.WriteLine("Message published!");
}
}
public interface ISender
{
void SendToBus(string message);
}
public class TestSender : ISender
{
private IEventBus<IEvent<long>, long> _bus { get; set; }
public TestSender(IEventBus<IEvent<long>,long> eventBus)
{
Console.WriteLine("Sender Initialized");
_bus = eventBus;
}
public void SendToBus(string message)
{
IEvent<long> env = new TestEvent
{
SourceId = 1,
Message = message
};
_bus.Publish(env);
}
}
public class TestEvent : IEvent<long>
{
public long SourceId { get; set; }
public string Message { get; set; }
}
class Program
{
static void Main(string[] args)
{
// It Is not worked: Exception: "GenericArguments violates the constraint of type paremeter "E""
IUnityContainer container = new UnityContainer().LoadConfiguration(ConfigurationManager.AppSettings["UnityContainer"]);
// This is worked
/*
IUnityContainer container = new UnityContainer();
IEventBus<IEvent<long>, long> bus = new TestEventBus<IEvent<long>, long>();
container.RegisterInstance<IEventBus<IEvent<long>, long>>(bus);
container.RegisterType<ISender, TestSender>(new TransientLifetimeManager(),
new InjectionConstructor(typeof(IEventBus<IEvent<long>, long>)));
*/
var sender = container.Resolve<ISender>();
sender.SendToBus("MyMessage");
Console.ReadKey();
}
}
所有项目代码:HERE
已解决
事实证明,Unity 不理解 Unity.config 文件中的嵌套泛型。解决方案:使用 Alias,并且 Alias One 不应使用其他别名。此配置 - 有效:
<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="TestUnityGeneric" />
<namespace name="TestUnityGeneric"/>
<alias alias="IEventLong" type="TestUnityGeneric.IEvent`1[System.Int64], TestUnityGeneric" />
<container name="Entity">
<register type="IEventBus`2[IEventLong,long]" mapTo="TestEventBus`2[IEventLong,long]"></register>
<register type="ISender" mapTo="TestSender">
<constructor>
<param name="eventBus" dependencyType="IEventBus`2[IEventLong, long]" />
</constructor>
</register>
</container>
</unity>