2012-01-03 17 views
2

とプロパティ定義をオーバーライド:私はReflection.Emit(TypeBuilder)を使用してこのパターンを実装しようとしているReflection.Emit

public class ClassToBeProxied 
{ 
    public virtual object Property1 { get; set; } 
} 

public class Proxy : ClassToBeProxied 
{ 
    [AttributeToBeAdded] 
    public override object Property1 
    { 
     get 
     { 
      //do something else to return the object - i.e get it from the database 
      return null; //stub 
     } 
     set 
     { 
      //do something else to set the object - i.e, save it to a database 
     } 
    }   
} 

私がやっていたすべてのgetおよびsetメソッドを傍受された場合、これは動作します:

PropertyInfo info = typeof(ClassToBeProxied).GetProperty("Property1", BindingFlags.Public | BindingFlags.Instance); 
{ 
    MethodBuilder pGet = typeBuilder.DefineMethod("get_" + info.Name, MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, info.PropertyType, Type.EmptyTypes); 
    ILGenerator pILGet = pGet.GetILGenerator(); 

    //The proxy object 
    pILGet.Emit(OpCodes.Ldarg_0); 
    //The database 
    pILGet.Emit(OpCodes.Ldfld, database); 
    //The proxy object 
    pILGet.Emit(OpCodes.Ldarg_0); 
    //The ObjectId to look for 
    pILGet.Emit(OpCodes.Ldfld, f); 
    pILGet.Emit(OpCodes.Callvirt, typeof(MongoDatabase).GetMethod("Find", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(ObjectId) }, null).MakeGenericMethod(info.PropertyType)); 
    pILGet.Emit(OpCodes.Ret); 

    MethodBuilder pSet = typeBuilder.DefineMethod("set_" + info.Name, MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new Type[] { info.PropertyType }); 
    ILGenerator pILSet = pSet.GetILGenerator(); 
    pILSet.Emit(OpCodes.Ldarg_0); 
    pILSet.Emit(OpCodes.Ldarg_1); 
    pILSet.Emit(OpCodes.Ldarg_0); 
    pILSet.Emit(OpCodes.Ldfld, database); 
    pILSet.Emit(OpCodes.Call, typeof(ProxyBuilder).GetMethod("SetValueHelper", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object), typeof(MongoDatabase) }, null)); 
    pILSet.Emit(OpCodes.Stfld, f); 
    pILSet.Emit(OpCodes.Ret); 

    //Edit: Added fix 
    newProp.SetSetMethod(pSet); 
    newProp.SetGetMethod(pGet); 
} 

でも、プロパティに属性を追加する必要があります。私はこれを行う方法を理解することはできません。

私は新しいPropertyDefinitionに追加する場合:

PropertyBuilder newProp = typeBuilder.DefineProperty(info.Name, PropertyAttributes.None, info.PropertyType, Type.EmptyTypes); 
newProp.SetCustomAttribute(new CustomAttributeBuilder(typeof(AttributeToBeAdded).GetConstructor(Type.EmptyTypes), Type.EmptyTypes, new FieldInfo[0], new object[0])); 

をして、生成された型のGetPropertiesの()を呼び出して、同じ名前の2つのプロパティが表示されます。しかし、コードを手作業でビルドして(上記の例のように)、typeof(Proxy).GetProperties()を呼び出すと、1つのProperty(派生クラスのプロパティ)しか表示されません。これは私が必要とする行動ですが、私はReflection.Emitと一緒にそこに着くことができません。

私は質問を明確にするためにもっと情報を追加する必要がある場合は教えてください。

+0

こんにちは@Joe Enzmingerは、ゲッターメソッドをオーバーライドする最も簡単な方法を詳細に追加できますか?提供されたコードは完全ではなく、私は各ステップで何をしているのかを理解しています。 ありがとう – Hilmi

+0

[this](https://gist.github.com/joeenzminger/7526426)のコードスニペットをご覧ください。 –

+0

ありがとう@Joe Enzminger。 – Hilmi

答えて

関連する問題