2012-01-11 13 views
1

を持っている場合は修正のコレクションを返す、私はコレクションを変更するには、静的メソッドのシリーズを持って判断しますかどうかを判断する方法があるアプリケーションの別の部分ではジェネリック型は、対応する実装

private static IEnumerable<Invoice> ResolveProxies(IEnumerable<Invoice> e) { 
    // do something to e 
    return e; 
} 

private static IEnumerable<Person> ResolveProxies(IEnumerable<Person> e) { 
    // do something to e 
    return e; 
} 

public static GridModel<T> ToGridModel<T>(this GridModel gridModel) { 
    // gridModel.Data is just IEnumerable 
    var collection = gridModel.Data as IEnumerable<T> ?? new List<T>(); 

    return new GridModel<T> { 
     Data = EvaluateDynamicProxies(collection), 
     Total = gridModel.Total 
    }; 
} 

private static IEnumerable<T> EvaluateProxies<T>(IEnumerable<T> collection) { 
    if (collection is IEnumerable<Invoice>) { 
     var enumeration = (collection as IEnumerable<Invoice>); 
     return ResolveProxies(enumeration) as IEnumerable<T>; 
    } 
    if (collection is IEnumerable<Person>) { 
     var enumeration = (collection as IEnumerable<Person>); 
     return ResolveProxies(enumeration) as IEnumerable<T>; 
    } 

    // proxy resolution isn't needed so return the unchanged collection 
    return collection; 
} 

有するそのような反復条件付きロジックは悪いコードのにおいである:それはそのタイプに変換することができ、その呼ばれるResolveProxiesメソッドを対応しているように、コレクションは、特定のタイプのものです。特定の型をマークして、対応するプロキシリゾルバメソッドがあることがわかったときに、何らかの型をマークする方法を考えるのには苦労しています。おそらくこのようなもの:

public interface IProxyResolver<out T> where T:IEnumerable<T> { 
    T ResolveProxies(); 
} 

これはどうやって使うのですか?実際に私は、コンパイラを依頼する方法が必要です:

  1. Tが一致ResolveProxiesメソッドを持っていますか?
  2. Tのプロキシを解決するクラスまたはメソッドの名前はどのようなものなので、そのインスタンスを取得して呼び出すことができますか?
+0

プロキシをクラス自体に入れなかった理由はありますか?そのクラスは、IProxyResolverを組み込むために指定されたインターフェイスまたは抽象クラスを暗示することができますか? – Lloyd

+0

@Lloydクラス( 'Invoice'、' Person'など)は、他のチームメンバが管理するPOCOプロジェクトの一部です。私たちはそのアプローチをとることを検討しましたが、実際にはPOCOの純度を取りません。 – Yuck

+0

属性を使用して、IProxyResolver名前空間を反復処理し、Types/SpecificProxyResolverのKey/Valueコレクションを構築する静的クラスのリフレクションを使用して、どのIProxyResolverクラスがどのクラスを処理するかを定義する属性を使用して、レゾルバが戻る?オーバーヘッドは初期静的初期化時のみです。 – Lloyd

答えて

1

IOC(Inversion of Control)フレームワークを使用できます。たとえば、私のチームはCastle Windsorを使用します。サービスを提供するサービス(通常はインターフェース)とタイプを登録することができます。これは、いくつかの素敵なジェネリック医薬品の解像度を持っているので、あなたは、このようなことを行うことができます:あなたは、ときT上記のクラスをregsiteredた場合

void SomeMethodThatNeedsAProxyResolver<T>(T obj) 
{ 
    var resolver = ioc.Resolve<IProxyResolver<T>>(); 
    //... 
} 

interface IProxyResolver<T> { /* whatever */ } 
class ProxyResolver<T> : IProxyResolver<T> { /* ... */ } 
class PersonProxyResolver : ProxyResolver<Person> { } 
class InvoiceProxyResolver : ProxyResolver<Invoice> { } 

そして、あなたはこのようなこれらのタイプを召喚することができますPersonまたはInvoiceの場合、ProxyResolverの適切で非ジェネリックなサブクラスを取得します。他のタイプの場合は、デフォルトの汎用スーパークラスを取得します。もちろん、あなたは物事を違ったものにすることができます。すべてのタイプに対して特定のプロキシリゾルバが必要な場合は、それも可能です。

+0

しかし、それはもう少しエレガントですが、条件のリストは間違いなく同じ考えです。 +1どちらの場合も+1 – Yuck

+0

IoCはおそらくこの問題に最も適していますが、私の場合、この1つのコードセクションのDIフレームワークへの依存性を追加することは正当化できません(残りのプロジェクトはIoCを必要としません) 。 – Yuck

1

カスタム属性の使用についてはどうですか?これは、など、カスタムシリアライザが選択されている方法を

であるあなたはAttributeクラスを定義することから始めたい:例えば、

public class ProxyResolverAttribute : Attribute { 
    public Type ResolverType { get; set; } 
    public ProxyResolver(Type resolverType) { ResolverType = resolverType; } 
} 

して、含まれているタイプにそれを置きます

[ProxyResolver(TypeOf(InvoiceProxyResolver))] 
public class Invoice ... { ... } 

は、コレクションで使用される一般的なタイプは、プロキシリゾルバのタイプを指定するかどうかを確認するためにリフレクションを使用します。

// Untested, beware of bugs 
var enumerationGenericType = enumeration.GetType().GetGenericArguments().FirstOrDefault(); 
var resolverAttribute = enumerationGenericType.GetType().GetCustomAttributes(TypeOf(ProxyResolverAttribute)).FirstOrDefault(); 

if (resolverAttribute != null) { 
    var resolverType = resolverAttribute.ResolverType; 
    // instanciate something of resolverType here 
} 

EDIT:あなたがに属性を適用したくない場合は、コメントを読みます含まれているオブジェクト、私はリストを継承し、そこに属性を適用するカスタムクラスを作成することをお勧めしたい

[ProxyResolver(TypeOf(InvoiceProxyResolver))] 
public class InvoiceList : List<Invoice> 
+0

明日これを見ていきます。入力いただきありがとうございます。 – Yuck

関連する問題