1

我正在寻找一个代码生成器(最好带有源代码),它允许我为我的代码中的泛型类生成包装类(使用反射)。

我做了一些搜索,但似乎找不到任何可以在这里做我需要的东西,所以我想在我开始写自己的之前先问这里。最终,我可能不得不自己写,但如果有人已经写过这样的东西,我至少想抢占先机。

解释我想要它做什么有点困难,但是生成器应该允许我指定我希望它为哪些泛型类生成包装器。它应该检查我指定的 DLL 中的类型,以确定哪些类型适合基于泛型类中的 where 约束。我在 linqpad 中编写了一些示例代码,并在“生成的代码”部分提供了示例输出。如您所见,它会根据泛型类中指定的约束生成所有类的组合。

我为什么要这样做?我有很多通用类,每个类都有许多类型参数(其中许多类型参数超过 10 个),我希望简化客户端代码(这还需要一些自定义工作以及一个代码生成器,该代码生成器会生成每个组合可能,但我可以处理)。完成之后,我可以将底层泛型类重构为更简单(不影响客户端代码),并且不需要像目前那样多的类型参数,这在现阶段并不完全可能。

void Main()
{
    var x = new GenBothFooAgainBarAgain();
    var y = new GenFFoo();
    var z = new GenFFooAgain();
    var a = new GenBothWithChildFooBarFooChild();
    var b = new GenBothWithChildFooBarAgainFooChild();
}

//////////////////////////////////Generated code ////////////////////////////////////
public class GenBothFooBar : GenBoth<Foo, Bar> {}
public class GenBothFooAgainBar : GenBoth<FooAgain, Bar> {}
public class GenBothFooBarAgain : GenBoth<Foo, BarAgain> {}
public class GenBothFooAgainBarAgain : GenBoth<FooAgain, BarAgain>{}
public class GenFFoo : GenF<Foo>{}
public class GenFFooAgain : GenF<FooAgain>{}

public class GenBothWithChildFooBarFooChild : GenBothWithChild<Foo, Bar, FooChild> {}
//public class GenBothWithChildFooAgainBarFooChild : GenBothWithChild<FooAgain, Bar, FooChild> {} - illegal - Don't generate this as FooChild doesn't inherit from FooAgain
public class GenBothWithChildFooBarAgainFooChild : GenBothWithChild<Foo, BarAgain, FooChild> {}
//public class GenBothWithChildFooAgainBarAgainFooChild : GenBothWithChild<FooAgain, BarAgain, FooChild>{} - illegal - Don't generate this as FooChild doesn't inherit from FooAgain


//////////////////////////////////Generated code ////////////////////////////////////

public class Foo : IFoo
{
    public string foo {get; set;}
}

public class FooChild : Foo, IFooChild
{
    public string fooChild {get; set;}
}

public class Bar : IBar
{
    public string bar {get; set;}
}

public class FooAgain : IFoo
{
    public string foo {get; set;}
}

public class BarAgain : IBar
{
    public string bar {get; set;}
}

public class GenF<F>
where F: class, IFoo, new()
{

}

public class GenBoth<F, B>
where F: class, IFoo, new()
where B: class, IBar, new()
{

}

public class GenBothWithChild<F, B, FChild>
where F: class, IFoo, new()
where B: class, IBar, new()
where FChild: class, F, IFooChild, new()
{

}

public interface IFooChild
{
    string fooChild {get; set;}
}

public interface IFoo
{
    string foo {get; set;}
}

public interface IBar
{
    string bar {get; set;}
}
4

1 回答 1

1

对于使用 c#/.net 知识生成代码,我建议您使用T4 - Visual Studio 免费提供的 Microsoft 文本模板引擎。感觉就像是 C# 和 ASP.NET 的混合体,因此您应该能够快速投入。

使用设计时模板,您可以指定现有的程序集并像往常一样反映它们,甚至可以使用Visual Studio 自动化代码模型来获取有关当前解决方案中的类的信息并从中生成代码。在您构建项目之前,此代码将在 Visual Studio 中生成。

使用运行时模板,您将“准备”如何在设计时生成代码的逻辑,为其提供程序集列表以在运行时处理和生成代码。

不幸的是,Visual Studio 缺乏 T4 模板的编辑功能,但有可用的免费工具,例如有形的 T4 编辑器

此代码片段可用于 T4 模板,并在 mscorlib.dll 中查找所有通用类并将它们写入输出文件:

<#
    foreach(System.Reflection.TypeInfo type in typeof(string).Assembly
                                                             .DefinedTypes
                                                             .Where(t => t.ContainsGenericParameters))
    {
#><#= type.Name #><<#= string.Join(", ", type.GenericTypeParameters.Select(tp => tp.Name)) #>>
<#  }
#>

希望这可以帮助

于 2013-04-17T08:32:15.017 回答