【发布时间】:2016-06-21 14:39:47
【问题描述】:
我有这个辅助方法SetProperty,它通过反射设置对象的属性。下面是我使用该方法的 2 个场景。第一种方法 CreateInstance 工作得很好,但第二种方法 Insert 不起作用。
在第二种方法中,对象上设置的属性会在 SetProperty 方法返回时丢失。我已经通过visual studio对其进行了调试。该对象具有设置到最后一个右花括号的属性。然后当控制权返回给调用者 Insert 时,Property 值将丢失。
设置属性的方法
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetProperty(object destination, string propertyName, object value)
{
var type = destination.GetType();
var property = type.GetProperty(propertyName);
var convertedVal = Convert(value, property.PropertyType);
property.SetValue(destination, convertedVal);
}
SetProperty 方法在此方法中运行良好
public static T CreateInstance<T>(SqlDataReader row, IEnumerable<CLASS> columns)
{
var type = typeof(T);
var obj = Activator.CreateInstance(type, true);
foreach (var column in columns)
{
SetProperty(obj, column.BackingPropertyName, column.Name);
}
return (T)obj;
}
SetProperty 方法在此方法中不起作用
public T Insert<T>(T obj, string table = null)
{
// CODE CHUNK
using (var conn = new SqlConnection(this.ConnectionString))
{
conn.Open();
using (var cmd = new SqlCommand(query.ToString(), conn))
{
// CODE CHUNK
var autoGeneratedValue = cmd.ExecuteScalar();
if (temp.AutoGeneratedColumn != null)
{
ReflectionHelper.SetProperty(
obj,
temp.AutoGeneratedColumn.BackingPropertyName,
autoGeneratedValue
);
}
}
}
return obj;
}
编辑 - 添加控制台应用以启用复制
要复制创建新的控制台应用程序,然后将此代码粘贴到 Program.cs(或等效项)中
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApplication1
{
public struct Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public int Age { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
var p = new Person
{
ID = 93
};
var res = SetProperty<Person>(ref p, "Age", 34);
Console.WriteLine(p.Age);
Console.WriteLine(res.Age);
Console.Read();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SetProperty<T>(ref T destination, string propertyName, object value)
{
var type = destination.GetType();
var property = type.GetProperty(propertyName);
var convertedVal = Convert(value, property.PropertyType);
property.SetValue(destination, convertedVal);
return (T)destination;
}
private static object Convert(object source, Type destinationType)
{
if (destinationType == null)
{
throw new ArgumentNullException("destinationType");
}
if (destinationType.IsGenericType &&
destinationType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
if (source == null)
{
return null;
}
destinationType = Nullable.GetUnderlyingType(destinationType);
}
return System.Convert.ChangeType(source, destinationType);
}
}
}
【问题讨论】:
-
你能在一个简单的控制台应用程序中重现这个吗?
-
也许你在第二个例子中的 T 是 struct 所以它作为值传递并且在 SetProperty 之后你有旧对象?
-
@MatthewWatson,“在控制台应用程序中重现”是什么意思。我把它作为一个类库,我也有一些单元测试可以让我遇到这种情况。
-
@ThatGuy 我的意思是其他人可以运行的最小且完整的复制,以便对其进行调查。
-
使用 ref 关键字传递对象,它应该可以正常工作
标签: c# .net reflection