3

これが可能であると確信していましたが、何らかの理由でこれを理解できないようです... Type から拡張メソッドを作成しようとしています。これは、その型のプロパティに Func を取り込みます、DefaultValueAttribute から DefaultValue を抽出します。

GetDefaultValue 関数呼び出しの型引数を指定した場合に限り、動作させることができます。現在持っているコードは次のとおりです。

個人エンティティ:

public class Person
{
    public string FirstName { get; set; }

    [DefaultValue("1234")]
    public string DOB { get; set; }
}

メソッドの呼び出し:

//Messing around in LinqPad - .Dump() is LinqPad method

//Works
//typeof(Person).GetDefaultValue<Person, string>(x=>x.DOB).Dump();

//Trying to get to work
//Can't figure out how to get it to infer that TIn is of the Type type.....
typeof(Person).GetDefaultValue(x=> x.DOB).Dump();

これは、メソッド呼び出しが行われる場所です...実際のプログラムに組み込む前に、今まさに手段を見つけようとしています...エラーチェックは、その方法を理解したら機能します。 、またはb / cをあきらめることはできません...

public static class Extensions
{
    //    Works
    //    public static TProperty GetDefaultValue<TModel, TProperty>(this Type type, Expression<Func<TModel, TProperty>> exp)
    //    {
    //        var property = typeof(TModel).GetProperties().ToList().Single(p => p.Name == GetFullPropertyName(exp));
    //        var defaultValue = (DefaultValueAttribute)property.GetCustomAttributes(typeof(DefaultValueAttribute), false).FirstOrDefault();
    //        return (TProperty)defaultValue.Value;
    //    }

    //trying to get to work
    //I know that I can't do the following, but it is basically what I am trying to do...  I think!
    public static TProperty GetDefaultValue<TProperty>(this Type type, Expression<Func<typeof(type), TProperty>> exp) 
    {
        var property = type.GetProperties().ToList().Single(p => p.Name == GetFullPropertyName(exp));
        var defaultValue = (DefaultValueAttribute)property.GetCustomAttributes(typeof(DefaultValueAttribute), false).FirstOrDefault();
        return (TProperty)defaultValue.Value;
    }

    //GetFullPropertyName c/o: http://stackoverflow.com/users/105570/
    //ref: http://stackoverflow.com/questions/2789504/
    public static string GetFullPropertyName<TModel, TProperty>(Expression<Func<TModel, TProperty>> exp)
    {
        MemberExpression memberExp;

        if (!TryFindMemberExpression(exp.Body, out memberExp))
               return String.Empty;

        var memberNames = new Stack<string>();
        do
            memberNames.Push(memberExp.Member.Name);
        while (TryFindMemberExpression(memberExp.Expression, out memberExp));

        return String.Join(".", memberNames.ToArray());
    }

    private static bool TryFindMemberExpression(Expression exp, out MemberExpression memberExp)
    {
        memberExp = exp as MemberExpression;
        if (memberExp != null)
            return true;

        if (IsConversion(exp) && exp is UnaryExpression)
        {
            memberExp = ((UnaryExpression)exp).Operand as MemberExpression;
            if (memberExp != null)
                return true;
        }    

        return false;
    }

    private static bool IsConversion(Expression exp)
    {
        return exp.NodeType == ExpressionType.Convert || exp.NodeType == ExpressionType.ConvertChecked;
    }
}

私は気が狂っていますか、それともこれは実際に可能ですか? よろしくお願いします。

4

1 に答える 1

2

というtypeof(Person)プロパティはありませんが、DOBタイプが Person のクラスにはあります。必要なのは、拡張メソッドをジェネリックにすることです。

public static TValue GetDefaultValue<TClass, TValue>(this TClass val, Expression<Func<TClass, TValue>> getter) {
    var type = typeof(TClass);
    var property = type.GetProperties().ToList().Single(p => p.Name == GetFullPropertyName(exp));
    var defaultValue = (DefaultValueAttribute)property.GetCustomAttributes(typeof(DefaultValueAttribute), false).FirstOrDefault();
    return (TProperty)defaultValue.Value;
}

そしてそれを次のように呼びます:

Person somePerson = GetMeAPerson();
somePerson.GetDefaultValue(p=>p.DOB);

上記をテストしていないことに注意してください。ただし、過去に同様のコードが機能するのを見たことがあります。そうは言っても、最初に Person インスタンスを作成する必要があるため、最初にやろうとしていたことはこの方法ではあまり魅力的ではないと思います。

別の、おそらくより魅力的なアプローチは、それを拡張メソッドにしないことです。

public static TValue GetDefaultValue<TClass, TValue>(Expression<Func<TClass, TValue>> getter) {
    var type = typeof(TClass);
    var property = type.GetProperties().ToList().Single(p => p.Name == GetFullPropertyName(exp));
    var defaultValue = (DefaultValueAttribute)property.GetCustomAttributes(typeof(DefaultValueAttribute), false).FirstOrDefault();
    return (TProperty)defaultValue.Value;
}

その後、インスタンスなしで呼び出すことができますが、推論はそれほどうまくいきません):

var defaultValue = GetDefaultValue<Person, DateTime>(p => p.DOB);
于 2012-07-31T19:59:05.577 に答える