我想用 C# IL 实现一个浅拷贝,而不是直接反射。
• ShallowCopy 版本直接反射:
public T ShallowCopy<T>(T instanceToShallowCopy) where T : class
{
Type type = instanceToShallowCopy.GetType();
T result;
try
{
result = System.Activator.CreateInstance(type) as T;
}
catch (MissingMethodException ex)
{
throw new MissingMethodException("The input instance type should contain default constructor.", ex);
}
catch (AggregateException ex)
{
throw new AggregateException("Activator create instance failed.", ex);
}
foreach (System.Reflection.PropertyInfo propertyInfo in instanceToShallowCopy.GetType().GetProperties())
{
if(propertyInfo.GetIndexParameters().Length == 0)
{
Object value = propertyInfo.GetValue(instanceToShallowCopy);
propertyInfo.SetValue(result, value);
}
}
foreach (System.Reflection.FieldInfo fieldInfo in instanceToShallowCopy.GetType().GetFields())
{
Object value = fieldInfo.GetValue(instanceToShallowCopy);
fieldInfo.SetValue(result, value);
}
return result;
}
• 我当前的 IL 版本代码是:
public static class PluginShallowCopyInvoker
{
public delegate Object ShallowCopyDelegate(Object paramType);
/// <summary>
/// Dictionary to cache any params fast constructor invokers, by type. Each entry is a shallowcopy delegates.
/// </summary>
private static ConcurrentDictionary<Type, ShallowCopyDelegate> InvokerCacheDictionary = new ConcurrentDictionary<Type, ShallowCopyDelegate>();
/// <summary>
/// T
/// </summary>
/// <param name="type"></param>
/// <param name="instanceToShallowCopy"></param>
/// <returns></returns>
public static ShallowCopyDelegate GenerateShallowCopyInvoker(Type type, Object instanceToShallowCopy)
{
ShallowCopyDelegate shallowCopyDelegate = null;
if (!InvokerCacheDictionary.TryGetValue(type, out shallowCopyDelegate))
{
shallowCopyDelegate = BuildShallwCopyInvokersForType(type, instanceToShallowCopy);
InvokerCacheDictionary.TryAdd(type, shallowCopyDelegate);
}
return shallowCopyDelegate;
}
/// <summary>
/// This is intent for do shallow copy, but now only create constructor. I don’t know how to do field/property copy.
/// </summary>
/// <param name="type"></param>
/// <param name="instanceToShallowCopy"></param>
/// <returns></returns>
private static ShallowCopyDelegate BuildShallwCopyInvokersForType(Type type, Object instanceToShallowCopy)
{
var invokeMethod = new DynamicMethod("PISC_" + type.FullName, typeof(Object), new Type[]{typeof(Object)}, true);
var ilgen = invokeMethod.GetILGenerator();
var cinfo = type.GetConstructor(Type.EmptyTypes);
if (cinfo == null) return null;
ilgen.Emit(OpCodes.Newobj, cinfo);
ilgen.Emit(OpCodes.Ret);
// I don’t know how to do field/property copy here … hope can got your help ~~~
return (ShallowCopyDelegate)invokeMethod.CreateDelegate(typeof(ShallowCopyDelegate));
}
public static void SetField(Type type, Object instanceToShallowCopy, ref Object newInstance)
{
foreach (System.Reflection.FieldInfo fieldInfo in instanceToShallowCopy.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
{
DynamicMethod dm = new DynamicMethod("setter", typeof(void), new Type[] { typeof(object), typeof(object) }, type, true);
ILGenerator setGenerator = dm.GetILGenerator();
setGenerator.Emit(OpCodes.Ldarg_0);
setGenerator.Emit(OpCodes.Unbox, type);
setGenerator.Emit(OpCodes.Ldarg_1);
if (fieldInfo.FieldType.IsValueType)
{
setGenerator.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
}
else
{
setGenerator.Emit(OpCodes.Unbox, fieldInfo.FieldType);
}
setGenerator.Emit(OpCodes.Stfld, fieldInfo);
setGenerator.Emit(OpCodes.Ret);
var value = fieldInfo.GetValue(instanceToShallowCopy);
newInstance = dm.Invoke(null, new object[]{newInstance, value});
}
}
我只知道如何构造一个实例,但我不知道如何复制他人的字段或属性。
有人可以帮我吗?
如果你能帮助我,真的很感激?