2014-08-31 8 views
-1

개체 속성을 사용하고 다시 개체 속성을 반환하는 함수를 만들려고합니다. 이 특정 함수로 속성 값을 가져 오는 방법.이 함수는 전체 개체가 아닌 개체의 특정 속성 만 사용합니다.개체 속성을 일반 함수로 전달하는 방법

class Program 
{ 

    public T MapFrom<T,V>(T SourceObject.property, V DestinationObject.Property) 
    //Not able to achieve this// 
    { 
    // Code to Map Property 
    } 


    // Here I want to specifically pass only one property of Object , not the entire one 
    ProgramClassObject.MapFrom<Details,Person>(Details.FirstName,Person.FName) 

    } 
} 

// Class Containing Property 
class Details 
{ 
    public string FirstName { get; set;}   
} 

// Class Containing Property 
class Person 
{ 
    public string FName { get; set;}   
} 
+2

[AutoMapper] (https://github.com/AutoMapper/AutoMapper)를 보셨습니까? – Noctis

답변

1

수동으로 할 수도 있고 라이브러리를 사용할 수도 있습니다 (주석, 누군가 그것에 대해 언급 한 내용 참조).

여전히 자신을 구현하려는 경우 :

준비 유용한 Expression 확장 :

public static B GetProperty<T, B>(this Expression<Func<T, B>> propertySelector, T target) where T : class 
{ 
    if (target == null) 
    { 
     throw new ArgumentNullException("target"); 
    } 

    if (propertySelector == null) 
    { 
     throw new ArgumentNullException("propertySelector"); 
    } 

    var memberExpression = propertySelector.Body as MemberExpression; 
    if (memberExpression == null) 
    { 
     throw new NotSupportedException("Only member expression is supported."); 
    } 

    var propertyInfo = memberExpression.Member as PropertyInfo; 
    if (propertyInfo == null) 
    { 
     throw new NotSupportedException("You can select property only. Currently, selected member is: " + 
             memberExpression.Member); 
    } 

    return (B)propertyInfo.GetValue(target); 
} 

public static void SetProperty<T, B>(this Expression<Func<T, B>> propertySelector, T target, B value) 
{ 
    SetObjectProperty(target, propertySelector, value); 
} 

public static void SetObjectProperty<T, B>(T target, Expression<Func<T, B>> propertySelector, object value) 
{ 
    if (target == null) 
    { 
     throw new ArgumentNullException("target"); 
    } 

    if (propertySelector == null) 
    { 
     throw new ArgumentNullException("propertySelector"); 
    } 

    var memberExpression = propertySelector.Body as MemberExpression; 
    if (memberExpression == null) 
    { 
     throw new NotSupportedException("Cannot recognize property."); 
    } 

    var propertyInfo = memberExpression.Member as PropertyInfo; 
    if (propertyInfo == null) 
    { 
     throw new NotSupportedException("You can select property only. Currently, selected member is: " + memberExpression.Member); 
    } 

    propertyInfo.SetValue(target, value); 
} 

MapFrom 구현 :

public static void MapFrom<TObject, TTarget, TProp>(TObject source, TTarget dest, 
    Expression<Func<TObject, TProp>> sourceSelector, Expression<Func<TTarget, TProp>> targetSelector) 
      where TObject : class where TTarget : class 
{ 
    var sourceValue = sourceSelector.GetProperty(source); 
    targetSelector.SetProperty(dest, sourceValue); 
} 

사용법 :

programClassObject.MapFrom(details, person, det => det.FirstName, per => per.FName); 
+0

sourceSelector.GetProperty (원본)에서 오류를 던지고 있습니다 –

+0

@ShriRam 어떤 예외 유형입니까? –

+0

@ShriRam 확장 메서드를 가져 오는 방법을 알고 있습니까? 확장 메서드를 선언 한 네임 스페이스에 대한'usage'가 누락되었습니다. –

1

expression과 같이 들리는 것 같습니다. 이것이 Entity Framework와 같은 일부 라이브러리가 통과 된 코드를 효과적으로 "구문 분석"하는 방법입니다.

먼저 다음과 같은 방법을 통해 표현식에서 PropertyInfo을 얻을 수 있습니다. 나는 이것을 아래에서 사용하는 방법을 설명 할 것이므로 나와 함께 감당해라.

public static PropertyInfo GetPropertyInfo<TIn, TOut>(Expression<Func<TIn, TOut>> PropertyExpression) 
{ 
    MemberExpression memberExpr; 
    switch (PropertyExpression.Body.NodeType) 
    { 
     case ExpressionType.MemberAccess: 
      memberExpr = (MemberExpression)PropertyExpression.Body; 
      break; 
     case ExpressionType.Convert: 
      memberExpr = (MemberExpression)((UnaryExpression)PropertyExpression.Body).Operand; 
      break; 
     default: 
      throw new NotSupportedException(); 
    } 

    var property = (PropertyInfo)memberExpr.Member; 
    return property; 
} 

그러면 메소드는 다음과 같이됩니다. 비록 당신이 원한다면 TOutobject으로 바꿀 수 있지만 데이터 유형이 동일하게 유지되도록 자유를 취했습니다. 저는 당신의 이름이 MapFrom 인 것을 기반으로했는데, 그것은 제가 속성이 "의사 소통"을 직접 의미한다고 믿게합니다. 당신이 모든 것을했으면

public T MapFrom<T, V, TOut>(Expression<Func<T, TOut>> Source, Expression<Func<V, TOut>> Destination) 
{ 
    var sourceProperty = GetPropertyInfo<T, TOut>(Source); 
    var destinationProperty = GetPropertyInfo<V, TOut>(Destination); 

    // Use those 
    // They're PropertyInfo instances, so it should be pretty easy to handle them however you would have expected to. 
} 

,

var ret = MapFrom<Person, Details, string>(c => c.FName, c => c.FirstName); 

당신은 어떤 유형의 인수를 지정할 필요가 없습니다 것 때문에, 일반적으로 입력 된 마스터 클래스의 사용을 통해이 정리 될 수있는 서명을 , string이 추측됩니다. 실제 상황에서는 그럴 가능성이 높습니다. 특히 다시 값을 매핑하는 것처럼 보이기 때문입니다.

+0

Console.WriteLine ("Please enter The value for {0}", sourceProperty.Name); var value = Console.ReadLine(); sourceProperty.SetValue (Source, value); var retrivedvalue = sourceProperty.GetValue (Source.Type, null); destinationProperty.SetValue (대상, retrivedvalue); return destinationProperty.GetValue (대상) .ToString(); –

+0

하지만 SourceProperty.Setvalue가 대상 예외 오류 –

+0

을 던지고 있습니다. 속성을 사용하여 개체를 전달해야하는 것처럼 들립니다. 이는 다른 문제이지만 비슷한 워크 플로를 통해 수행 할 수 있습니다. 'MapFrom' 시그니처에'T'와'V' 타입의 두 매개 변수를 각각 추가 한 다음,이를 사용하여'GetValue'와'SetValue'를 호출하면됩니다. 표현식이 원래 값 유형이 아니기 때문에 표현식에 대해 호출 할 수 없습니다. –

관련 문제