C# generics wrapper generator

白昼怎懂夜的黑 提交于 2019-12-24 15:57:38

问题


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

回答1:


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



来源:https://stackoverflow.com/questions/16053665/c-sharp-generics-wrapper-generator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!