2012-02-01 23 views
1

我正在用C#做代码生成,我想在一个getter中建立一个后台字段。使用代码生成一个集合的铸造项目

下面是一个例子:

public class Potato 
{ 
} 

public class ProxyPotato : Potato 
{  
} 

public class Stew 
{ 
    private ICollection<ProxyPotato> _proxyPotatoes; 

    //This is the code I would like to generate (specialy the cast part) 
    public ICollection<Potato> Potatoes { get { return _proxyPotatoes.Cast<Potato>().ToList(); } } 
} 

我有这样的代码可以生成一个属性,但我不知道如何执行主演:

private static void SetProperty(TypeBuilder builder, string propertyName, Type propertyType, FieldBuilder fieldBuilder) 
{ 
    const string GetterPrefix = "get_"; 
    const string SetterPrefix = "set_"; 

    // Generate the property 
    var propertyBuilder = builder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null); 


    // Property getter and setter attributes. 
    const MethodAttributes propertyMethodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Virtual; 

    // Define the getter method. 
    var getterMethod = builder.DefineMethod(string.Concat(GetterPrefix, propertyName), propertyMethodAttributes, propertyType, Type.EmptyTypes); 

    // Emit the IL code. 
    // ldarg.0 
    // ldfld,_field 
    // ret 
    ILGenerator getterILCode = getterMethod.GetILGenerator(); 
    getterILCode.Emit(OpCodes.Ldarg_0); 
    getterILCode.Emit(OpCodes.Ldfld, fieldBuilder); 
    getterILCode.Emit(OpCodes.Ret); 

    // Define the setter method. 
    MethodBuilder setterMethod = builder.DefineMethod(
    string.Concat(SetterPrefix, propertyName), 
    propertyMethodAttributes, null, new Type[] { propertyType }); 

    // Emit the IL code. 
    // ldarg.0 
    // ldarg.1 
    // stfld,_field 
    // ret 
    ILGenerator setterILCode = setterMethod.GetILGenerator(); 
    setterILCode.Emit(OpCodes.Ldarg_0); 
    setterILCode.Emit(OpCodes.Ldarg_1); 
    setterILCode.Emit(OpCodes.Stfld, fieldBuilder); 
    setterILCode.Emit(OpCodes.Ret); 

    propertyBuilder.SetGetMethod(getterMethod); 
    propertyBuilder.SetSetMethod(setterMethod); 
} 
+0

这不是铸造。这只是对静态[Enumerable.Cast 方法](http://msdn.microsoft.com/en-us/library/bb341406.aspx)的调用。 – dtb 2012-02-01 21:11:32

+0

我只是好奇,你实际工作的背景是什么?我从来没有做过这样的事情,并想知道它什么时候开始。 – 2012-02-01 21:13:04

+0

@dtb你是对的!我将重新命名为:如何使用OpCodes.Call发出相当于Cast () – W3Max 2012-02-01 21:19:08

回答

3

演员阵容扩展方法是方法调用。您需要发出以下内容:

return Enumerable.ToList<Potato>(Enumerable.Cast<Potato>(_proxyPotatoes)); 

您可以使用OpCodes.Call指令调用这些静态方法。

+2

对,并记住,这是'Enumerable.ToList (Enumerable.Cast (_proxyPotatoes));':编译器通常会自动提供泛型参数在这里,但如果你手动做,你需要指定它。 – hvd 2012-02-01 21:15:42

+0

@ hvd我编辑了这个。我忘了,因为我从来没有这样写过;-) – usr 2012-02-01 21:16:58

+1

你是对的!我将重命名该问题为:如何使用OpCodes.Call来发出返回Enumerable.ToList(Enumerable.Cast (_proxyPotatoes));对不起,但我是代码生成的新手! – W3Max 2012-02-01 21:20:12