我正在尝试创建一个接受对象属性并返回对象属性的函数。 如何将属性值放入此特定函数中,以便此函数只接受对象的特定属性而不是整个对象?
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;}
}
答案 0 :(得分: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;
}
然后,该方法将成为这样的。我已经冒昧地确保这里的数据类型相同,但如果您愿意,可以将TOut
更改为object
。我根据您的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
。在现实世界的情况下,这可能是你想做的事情,特别是因为你似乎再次映射价值。
答案 1 :(得分: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);