2016-08-18 8 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を参照しています。

私はUnityをインストールし、コンテナをロード中のいずれかの手順を同様に達成されてい私のメインアプリで

:各「ジョブ」

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

独自のクラスのプロジェクトで定義され、がによって参照されていませんメインアプリ。各「仕事」はとIJobから継承する必要があります。

メインアプリケーションには、単純なRESTサービスが公開されています。私はJobNameに基づいて、コンテナからオブジェクトを引くしようとしていますメインアプリで

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

:あなたのような何かを投稿することができます。私は(はい、私はそれが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を操作する方法はたくさんあります。

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; } 
} 

私は、次のことができます。

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

は私が最小ペイロードのための小さなモデルを作成しました:私はまた、拡張メソッドを構築し

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); 

:これは、これまで働くことになったものです直接(JSON)のスタイリングペイロードから仕事を得る:

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はコアに存在します。ジョブクラスは自分の図書館に住んでいます(あるいは、私が思うにもメインプログラムに住むことができます)。

関連する問題