C#泛型包装发生器发生器

2023-09-06 15:54:03 作者:乱世称帝王

我在寻找一个code发生器(preferably与源),让我产生的包装类(使用反射)的泛型类,我在我的code

我已经做了一些搜索,但似乎无法找到任何东西,会做什么,我需要在这里,所以我想我会在这里问我开始写我自己的了。最终,我可能会写我自己,但希望至少可以得到一个良好的开端如果有人已经写了这样的事情。

这是一个有点难以解释什么,我想要它做的,但发生器应该让我指定我希望它生成包装该泛型类。它应该通过我指定,以确定哪些将适合的基础上,其中限制了通用类的DLL类型。我已经写了一些样品code在linqpad与生成的code一节中的例子输出。正如你可以看到它产生的,它可以根据在通用类指定的限制类所有组合。

我为什么要这么做?我有相当多的普通班,每班有许多类型的参数(其中有许多向上10型PARAMS),我想客户端code加以简化(这也将需要一些定制工作连同$ C $该毯产生每一个可能的组合,但我可以处理)C发生器。经过这样做了,我就可以重构底层的泛型类要简单一些(在不影响客户端code)和,因为他们目前所面对的,这是不完全有可能在这个阶段并不需要那么多的类型参数。

 无效的主要()
{
    VAR X =新GenBothFooAgainBarAgain();
    变种Y =新GenFFoo();
    变种Z =新GenFFooAgain();
    VAR一个=新GenBothWithChildFooBarFooChild();
    变种B =新GenBothWithChildFooBarAgainFooChild();
}

//////////////////////////////////产生code /////////// /////////////////////////
公共类GenBothFooBar:GenBoth<富,酒吧和GT; {}
公共类GenBothFooAgainBar:GenBoth< FooAgain,酒吧> {}
公共类GenBothFooBarAgain:GenBoth<富,BarAgain> {}
公共类GenBothFooAgainBarAgain:GenBoth< FooAgain,BarAgain> {}
公共类GenFFoo:GenF<富> {}
公共类GenFFooAgain:GenF< FooAgain> {}

公共类GenBothWithChildFooBarFooChild:GenBothWithChild<富,酒吧,FooChild> {}
//公共类GenBothWithChildFooAgainBarFooChild:GenBothWithChild< FooAgain,酒吧,FooChild> {}  - 非法 - 不产生这样的FooChild没有从FooAgain继承
公共类GenBothWithChildFooBarAgainFooChild:GenBothWithChild<富,BarAgain,FooChild> {}
//公共类GenBothWithChildFooAgainBarAgainFooChild:GenBothWithChild< FooAgain,BarAgain,FooChild> {}  - 非法 - 不产生这样的FooChild没有从FooAgain继承


//////////////////////////////////产生code /////////// /////////////////////////

公共类Foo:IFoo的
{
    公共字符串FOO {获得;组;}
}

公共类FooChild:美孚,IFooChild
{
    公共字符串fooChild {获得;组;}
}

公共类酒吧:伊巴尔
{
    公共字符串吧{获得;组;}
}

公共类FooAgain:IFoo的
{
    公共字符串FOO {获得;组;}
}

公共类BarAgain:伊巴尔
{
    公共字符串吧{获得;组;}
}

公共类GenF< F>
其中F:类IFoo的,新的()
{

}

公共类GenBoth< F,B>
其中F:类IFoo的,新的()
其中B:类,动物资源局,新的()
{

}

公共类GenBothWithChild< F,B,FChild>
其中F:类IFoo的,新的()
其中B:类,动物资源局,新的()
其中,FChild:类F,IFooChild,新的()
{

}

公共接口IFooChild
{
    字符串fooChild {获得;组;}
}

公共接口IFoo的
{
    字符串FOO {获得;组;}
}

公共接口伊巴尔
{
    串吧{获得;组;}
}
 

解决方案使用C#/。NET知识

有关code代我想指出你使用的 T4 - 微软的文本模​​板引擎,它是免费的Visual Studio。这感觉就像C#和ASP.NET之间的混合,所以你应该能够迅速潜水

使用的设计时模板,您可以指定现有的程序集和反映他们作为你通常会做的,甚至使用的 Visual Studio的自动化codeModel ,以获得有关类的信息当前解决方案内,生成code它。这code将在Visual Studio中生成生成项目之前。

使用的运行时模板,你会prepare如何产生code在设计时,为它提供组件列表来处理和生成逻辑code运行时。

不幸的是Visual Studio中缺乏编辑功能的T4模板,但也有类似的有形的T4编辑。

冲击高压发生器 信号发生器

这code片段可在T4模板使用,并查找所有泛型类在mscorlib.dll中,并将其写入到输出文件:

 <#
    的foreach(System.Reflection.TypeInfo类型typeof运算(字符串).Assembly
                                                             .DefinedTypes
                                                             。凡(T => t.ContainsGenericParameters))
    {
#>&其中;#= type.Name#>&其中;&其中;#=的string.join(,,type.GenericTypeParameters.Select(TP => tp.Name))#>>
<#}
#>
 

希望这有助于

I'm looking for a code generator (preferably with source) that will allow me to generate wrapper classes (using reflection) for generic classes that i have in my code.

I've done a bit of searching but can't seem to find anything that will do what i need here, so i thought i'd ask here before i start writing my own. Ultimately, i'll probably have to write my own but would like to at least get a head start if someone's already written something like this.

It's a little difficult to explain what i want it to do, but the generator should allow me to specify which generic classes i want it to generate wrappers for. It should go through the types in DLLs that i've specified to determine which ones would fit based on the where constrains in the the generic classes. I've written some sample code in linqpad with example output in the "Generated Code" section. As you can see it generates all combinations of classes that it can based on the constraints specified in the generic classes.

Why do i want to do this? I've got quite a few generic classes each with many type parameters (many of which have upwards of 10 type params) and i want client code to be simplified (which will also require some custom work along with a code generator that blanket generates every combination possible, but that i can deal with). After that's done, i can then refactor the underlying generic classes to be simpler (without affecting client code) and not require as many type parameters as they have at the moment, which isn't entirely possible at this stage.

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;}
}

解决方案

For code generation using c#/.net knowledge I would point you to use T4 - microsoft's text templating engine that comes free with Visual Studio. It feels like a mixture between C# and ASP.NET, so you should be able to dive in quickly.

Using a Design-Time Template, you can specify existing Assemblies and reflect them as you would normally do or even use the Visual Studio Automation CodeModel to gain information about classes inside your current Solution and generate code from it. This code would be generated inside Visual Studio before you build your project.

Using a Run-Time Template, you would "prepare" the logic of how to generate code at design time, provide it with a list of assemblies to process and generate code at runtime.

Unfortunately Visual Studio lacks editing features for T4 templates, but there are free tools available like tangible's T4 Editor.

This code snippet can be used in a T4 template and finds all generic classes in the mscorlib.dll and writes them in the output file:

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

Hope this helps