MS Unity 中的重复对象名称(应用程序块)
Duplicate object names in MS Unity (App Block)
我会尽量简化!
Unity注册篇:
// ====================================================================
// NOTE: This fails as the WithName.TypeName is Payload for all jobs!
// HOW can we make the name for payloads "[JobName].Payload"??
// ====================================================================
_container.RegisterTypes(AllClasses.FromAssembliesInBasePath()
.Where(type => (typeof(IJob).IsAssignableFrom(type) || typeof(IJobPayload).IsAssignableFrom(type)) && type.IsClass),
WithMappings.FromAllInterfaces,
WithName.TypeName,
WithLifetime.Transient);
其中:
public interface IJob
{
bool Execute<T>(T payload) where T : class, IJobPayload;
}
public interface IJobPayload
{
string JobName { get; set; }
string JobQueueName { get; set; }
int Id { get; set; }
JobType JobType { get; set; }
CronExpression Cron { get; set; }
}
现在我们可以创建各种工作了。类似于:
public class Job1 : IJob
{
bool IJob.Execute<T>(T payload)
{
if (typeof(T) != typeof(Payload))
throw new ArgumentException($"Expecting an object with a type of {typeof(Payload)}!");
Console.WriteLine("public class Job1 : IJob");
return false;
}
public class Payload : IJobPayload
{
public string JobName { get; set; }
public string JobQueueName { get; set; }
public int Id { get; set; }
public JobType JobType { get; set; }
public CronExpression Cron { get; set; }
// --- job specific data -------------------
public string Job1ExtraData { get; set }
public datetime Job1Created { get; set }
}
}
public class Job2 : IJob
{
bool IJob.Execute<T>(T payload)
{
if (typeof(T) != typeof(Payload))
throw new ArgumentException($"Expecting an object with a type of {typeof(Payload)}!");
Console.WriteLine("public class Job2 : IJob");
return false;
}
public class Payload : IJobPayload
{
public string JobName { get; set; }
public string JobQueueName { get; set; }
public int Id { get; set; }
public JobType JobType { get; set; }
public CronExpression Cron { get; set; }
// --- job specific data -------------------
public string Title { get; set }
public int Count { get; set }
}
}
当试图解决 Job1.Payload
或 Job2.Payload
的具体 class 时,问题就来了。两者在 Unity 中的名称相同:Payload
!
由于我正在处理的项目有很多很多工作,我们想要构建一个模板来创建新工作(添加 > 工作),我们更喜欢将有效负载模型作为工作的子项。
现在我有控制器代码接受 Payload
对象的 JSON 表示:
[HttpPost]
public void Post(dynamic json)
{
var container = UnityHelpers.GetConfiguredContainer();
var jobName = GetJobNameFromJson(json); // JsonConverter will not work until I can resolve *which* payload definition I want, brute force it for now...
var job = container.Resolve<IJob>(jobName);
// ====================================================================
// how do I get it to a point where this will resolve.
// (see original NOTE at top of question)
// ====================================================================
var payload = container.Resolve(typeof(IJobPayload), $"{jobName}.Payload");
job.Execute(payload);
}
如何在 Unity(或任何其他 IoC 容器)中使用它?
您正在使用的 RegisterTypes
重载的第三个参数是 Func<Type,string>
类型。 RegisterTypes
方法将为它找到的每个类型调用此委托以获得注册名称。
WithName.TypeName
只是一个静态方法,returns 类型的名称。
您可以创建自己的方法或 lambda 表达式,它们足够智能以检测类型是否为嵌套类型。这是一个例子:
t => t.IsNested ? t.DeclaringType.Name + "." + t.Name : t.Name
因此您的注册声明将如下所示:
_container.RegisterTypes(
AllClasses.FromAssembliesInBasePath()
.Where(type => (typeof(IJob).IsAssignableFrom(type) || typeof(IJobPayload).IsAssignableFrom(type)) && type.IsClass),
WithMappings.FromAllInterfaces,
t => t.IsNested ? t.DeclaringType.Name + "." + t.Name : t.Name,
WithLifetime.Transient);
我会尽量简化!
Unity注册篇:
// ====================================================================
// NOTE: This fails as the WithName.TypeName is Payload for all jobs!
// HOW can we make the name for payloads "[JobName].Payload"??
// ====================================================================
_container.RegisterTypes(AllClasses.FromAssembliesInBasePath()
.Where(type => (typeof(IJob).IsAssignableFrom(type) || typeof(IJobPayload).IsAssignableFrom(type)) && type.IsClass),
WithMappings.FromAllInterfaces,
WithName.TypeName,
WithLifetime.Transient);
其中:
public interface IJob
{
bool Execute<T>(T payload) where T : class, IJobPayload;
}
public interface IJobPayload
{
string JobName { get; set; }
string JobQueueName { get; set; }
int Id { get; set; }
JobType JobType { get; set; }
CronExpression Cron { get; set; }
}
现在我们可以创建各种工作了。类似于:
public class Job1 : IJob
{
bool IJob.Execute<T>(T payload)
{
if (typeof(T) != typeof(Payload))
throw new ArgumentException($"Expecting an object with a type of {typeof(Payload)}!");
Console.WriteLine("public class Job1 : IJob");
return false;
}
public class Payload : IJobPayload
{
public string JobName { get; set; }
public string JobQueueName { get; set; }
public int Id { get; set; }
public JobType JobType { get; set; }
public CronExpression Cron { get; set; }
// --- job specific data -------------------
public string Job1ExtraData { get; set }
public datetime Job1Created { get; set }
}
}
public class Job2 : IJob
{
bool IJob.Execute<T>(T payload)
{
if (typeof(T) != typeof(Payload))
throw new ArgumentException($"Expecting an object with a type of {typeof(Payload)}!");
Console.WriteLine("public class Job2 : IJob");
return false;
}
public class Payload : IJobPayload
{
public string JobName { get; set; }
public string JobQueueName { get; set; }
public int Id { get; set; }
public JobType JobType { get; set; }
public CronExpression Cron { get; set; }
// --- job specific data -------------------
public string Title { get; set }
public int Count { get; set }
}
}
当试图解决 Job1.Payload
或 Job2.Payload
的具体 class 时,问题就来了。两者在 Unity 中的名称相同:Payload
!
由于我正在处理的项目有很多很多工作,我们想要构建一个模板来创建新工作(添加 > 工作),我们更喜欢将有效负载模型作为工作的子项。
现在我有控制器代码接受 Payload
对象的 JSON 表示:
[HttpPost]
public void Post(dynamic json)
{
var container = UnityHelpers.GetConfiguredContainer();
var jobName = GetJobNameFromJson(json); // JsonConverter will not work until I can resolve *which* payload definition I want, brute force it for now...
var job = container.Resolve<IJob>(jobName);
// ====================================================================
// how do I get it to a point where this will resolve.
// (see original NOTE at top of question)
// ====================================================================
var payload = container.Resolve(typeof(IJobPayload), $"{jobName}.Payload");
job.Execute(payload);
}
如何在 Unity(或任何其他 IoC 容器)中使用它?
您正在使用的 RegisterTypes
重载的第三个参数是 Func<Type,string>
类型。 RegisterTypes
方法将为它找到的每个类型调用此委托以获得注册名称。
WithName.TypeName
只是一个静态方法,returns 类型的名称。
您可以创建自己的方法或 lambda 表达式,它们足够智能以检测类型是否为嵌套类型。这是一个例子:
t => t.IsNested ? t.DeclaringType.Name + "." + t.Name : t.Name
因此您的注册声明将如下所示:
_container.RegisterTypes(
AllClasses.FromAssembliesInBasePath()
.Where(type => (typeof(IJob).IsAssignableFrom(type) || typeof(IJobPayload).IsAssignableFrom(type)) && type.IsClass),
WithMappings.FromAllInterfaces,
t => t.IsNested ? t.DeclaringType.Name + "." + t.Name : t.Name,
WithLifetime.Transient);