1

ジェネリックメソッドで辞書を操作できるようにしたいと思います。私が探しているのは、ジェネリック拡張メソッドLoadPropertyに送信されたディクショナリのキーと値からタイプを取得する方法です。

これは私がこれまでに行ったことです。

メソッドを拡張機能として呼び出します

entityObject.LoadProperty<Dictionary<string, int>>("CartonThreshold")
//entityObject.LoadProperty<Dictionary<string, double>>("CartonThreshold")

// ... 

public static T LoadProperty<T>(this EntityObject entity, string name) where T : new()
{
    EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));

    // If request dictionary
    if (typeof(T).GetInterface(typeof(IDictionary<,>).Name) != null || typeof(T).Name.Contains("IDictionary"))
    {
        var dictionaryInstance = (IDictionary)new T();

        // Just for testing
        var a = dictionaryInstance.Keys.GetType().Name;
        var b = dictionaryInstance.Values.GetType().Name;

        var key = (T) Convert.ChangeType(prop.Name, typeof (T));
        var value = (T) Convert.ChangeType(prop.Value, typeof (T));
        dictionaryInstance.Add(key, value);
        return (T) dictionaryInstance;
    }

    // default
    return (T)Convert.ChangeType(prop.Value, typeof(T));
}

目標は、正しく型指定された辞書を返すことです

4

4 に答える 4

1

私が探していたのは、GetType()のGetGenericArguments()拡張機能でした。

以下のメソッドは、必要なものを返します。

public static T LoadProperty<T>(this EntityObject entity, string name) where T : new()
{
    EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));

    try
    {
        // If request dictionary
        if (typeof(T).GetInterface(typeof(IDictionary<,>).Name) != null || typeof(T).Name.Contains("IDictionary"))
        {
            var dictionaryInstance = (IDictionary)new T();

            var typing = dictionaryInstance.GetType().GetGenericArguments();
            Type keyType = typing[0];
            Type valueType = typing[1];

            // dictionary fallback, set to default of the valuetype if null
            object value = prop.Value != null ? Convert.ChangeType(prop.Value, valueType) : Activator.CreateInstance(valueType);
            var key = Convert.ChangeType(prop.Name, keyType);
            dictionaryInstance.Add(key, value);
            return (T)dictionaryInstance;
        }

        if (prop.Value != null)
        {
            // default
            return (T)Convert.ChangeType(prop.Value, typeof(T));
        }
    }
    catch { }
    return default(T);
}

このようにして、このようなメソッドを呼び出すことができます

// Will return a typed dictionary with the EntityObjectProperty name as key and the EntityObjectProperty Value as value
entityObject.LoadProperty<Dictionary<string, int>>("CartonThreshold")

// Will return a string of the EntityObjectProperty Value
entityObject.LoadProperty<string>("CartonThreshold")

// Will return an Int of the EntityObjectProperty Value
entityObject.LoadProperty<int>("CartonThreshold")
于 2012-07-06T13:15:55.367 に答える
0

次のようにメソッドを定義してみませんか。

public static IDictionary<K, V> LoadProperty<K, V>(this EntityObject entity, string name)
于 2012-07-06T13:15:48.250 に答える
0

私があなたの質問を正しく理解した場合、あなたがしたいことは次のようにあなたのメソッドを定義することです:

public static T LoadProperty<T,TKey,TValue>(this EntityObject entity, string name) 
    where T : IDictionary<TKey,TValue>, new() {
    EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));
    T t = new T();
    t.Add((TKey)prop.Name, TValue(prop.Value));
    return t;
}

それからそれを

Dictionary<string,int> property = entityObject.LoadProperty<Dictionary<string,int>, string, int>("test");

悪い点は、毎回すべての汎用パラメーターを指定する必要があることです...
具体的なケースで問題がなければ、次のようにはるかに簡単になります。

public static IDictionary<TKey,TValue> LoadProperty<TKey,TValue>(this EntityObject entity, string name) {
    EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));
    var dict = new Dictionary<TKey,TValue>();
    dict.Add((TKey)prop.Name, TValue(prop.Value));
    return dict;
}

編集:あなたの明確化の後、一般的な引数の数によって2つのケースを区別するのはどうですか?

public static IDictionary<TKey,TValue> LoadProperty<TKey,TValue>(this EntityObject entity, string name) {
    var d = new Dictionary<TKey,TValue>();
    // add value from EntityObject 
    return t;
}

public static TValue LoadProperty<TValue>(this EntityObject entity, string name) {
    TValue ret;
    // get value from EntityObject 
    return ret;
}
于 2012-07-06T13:11:28.733 に答える
0

ほとんどすべてのもので機能させるために、関数を渡して、必要な戻り型を作成できます。

public static T LoadProperty<TKey,TValue,T>(this EntityObject entity, string name,  Func<TKey,TValue,T> createWhatever) 
{
    EntityObjectProperty prop = entity.Properties.Single(x => x.Name.Equals(name));
    return createWhatever((TKey)prop.Name, (TValue)prop.Value);
}

ただし、これは呼び出し時にもう少し冗長になります。

于 2012-07-06T13:29:26.213 に答える