2016-08-18 66 views
0

我有一个处理程序方法的应用程序。处理程序方法获取一个json字符串,其中包含需要处理请求的对象的名称以及请求的参数。基本上,东西(我会保持它的简单)是这样的:使用Unity来获取基于名称的对象

public interface IJob 
{ 
    bool Execute(); 
    bool Hydrate(string source); 
} 

public class JobBase 
{ 
    public int Id { get; set; } 
    public JobType JobType { get; set; } 
    public CronExpression CronExpression { get; set; } 
} 

public class JobSubmitClone : JobBase, IJob 
{ 
    public string[] Tokens { get; set; } 

    public bool Hydrate(string source) 
    { 
     // code omitted... 
     return true; 
    } 
    public bool Execute() 
    { 
     // code omitted... 
     return true; 
    } 
} 

IJob和JobBase都保存在一个公共类项目。所有应用程序引用此DLL。

在我的主要应用程序,我已经安装了统一和装载容器中的一个步骤来完成,如:

// Scan assemblies for Job definitions... 
_container.RegisterTypes(AllClasses.FromAssembliesInBasePath(). 
    Where(type => typeof(IJob).IsAssignableFrom(type)), 
    WithMappings.FromAllInterfaces, 
    WithName.TypeName, 
    WithLifetime.Transient); 

每个“工作”,在自己的类项目是指,是不是通过引用主要的应用程序。每个“作业”必须继承自JobBaseIJob

主应用程序有一个简单的REST服务暴露。您可以发表类似:

{ jobName : JobSubmitClone, Id : 1, JobType : 2, CronExpression : '' } 

在主应用程序,我想从基于JobName集装箱拉的对象。我已经试过这(是的,我知道这违反了IoC模式):

var container = UnityHelpers.GetConfiguredContainer(); 
var job = container.Resolve<IJob>(myParams.jobName); // "JobSubmitClone" // 
var hydrated = job.Hydrate(myParams); 
if(hydrated) 
    var result = job.Execute(); 

我收到以下错误:

Exception is: InvalidOperationException - The current type, IJob, is an interface and cannot be constructed. Are you missing a type mapping?

我缺少什么?

回答

0

原来,有很多方法来操作Unity。这是结束了,到目前为止的工作:

container.RegisterTypes(
    AllClasses.FromLoadedAssemblies().Where(type => typeof(IJob).IsAssignableFrom(type) && type.IsClass), 
    WithMappings.FromAllInterfaces, 
    t => t.IsNested ? t.DeclaringType.Name + "." + t.Name : t.Name, 
    WithLifetime.Transient); 

我还内置了一个扩展方法:

public static IJob Job(this string src) 
{ 
    var container = UnityConfig.GetConfiguredContainer(); 
    var job = container.Resolve<IJob>(src); 
    return job; 
} 

我创建了最小载荷小模型:

public class MinimumCommandModel : IRequest<MinimumResultModel> 
{ 
    public MinimumCommandModel(string json) 
    { 
     FullPayloadString = json; 
     MinimumPayload = JsonConvert.DeserializeObject<MinimumPayload>(json); 
    } 

    public string MinimumPayloadString => JsonConvert.SerializeObject(MinimumPayload); 
    public string FullPayloadString { get; set; } 
    public MinimumPayload MinimumPayload { get; set; } 
} 

我可以再直接从(JSON)sting有效载荷中获得工作:

var command = new MinimumCommandModel(Request.Content.ReadAsStringAsync().Result); 
var job = command.MinimumPayload.JobName.Job(); 
0

Each "Job" is defined in its own class project and is NOT referenced by the main app. Each "Job" must inherit from JobBase and IJob.

你看过MEF吗?它有能力通过元数据查询和加载类。我倾向于将Unity用于已知的编译时依赖关系,而MEF用于运行时加载的动态程序集。 (没有理由不能在同一个项目中同时使用这两个项目。)

我认为我们做了类似于您要找的东西。我们根据他们的类名加载工作流。

只是装饰用System.ComponentModel.Composition.MetadataAttribute作业....

[MetadataAttribute] 
public class WorkflowMetadataAttribute : Attribute, IWorkflowMetadata 
{ 
    public WorkflowMetadataAttribute(string typeName) { 
     TypeName = typename; 
    } 
    public string TypeName { get; private set; } 
} 

,你把你要导出的事....

public interface IWorkflow // aka IJob 
{ 
    void Execute(); 
} 

[Export(typeof(IWorkflow))] 
[WorkflowMetadata("WhateverWorkflow")] 
public class WhateverWorkflow : IWorkflow 
{ 
    public void Execute() { } 
} 

的导出的类可以与运行它的项目分开构建。如果将其作为库构建到单独的程序集中,则可以在导入程序类中加载程序集(或程序集的目录)。

public class WorkflowCatalog : IPartImportsSatisfiedNotification 
{ 
    [ImportMany] 
    public IEnumerable<Lazy<IWorkflow, IWorkflowMetadata>> Workflows { get; private set; } 

    public void Compose() { 
     var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 
     var catalog = new DirectoryCatalog(path); 
     var compositionContainer = new CompositionContainer(catalog); 
     compositionContainer.ComposeParts(this); 
    } 

    public void OnImportsSatisfied() { 
     var workflow = Workflows.Single(w => w.Metadata.TypeName == "WhateverWorkflow").Value; 
     workflow.Execute(); 
    } 
} 

IJob,IJobMetadata和JobBase存在于核心中。工作班生活在他们自己的图书馆(或者我想他们也可以住在主要的程序中)。