我听到有人指出,代码生成器和T4模板不应使用。背后的逻辑是,如果您正在使用一台发电机产生的代码再有就是通过构建泛型和模板的代码更好更有效的方式。

虽然我稍微高于这个说法,我还没有真正找到建立模板,可以说,例如实例自己的有效方法。 。换句话说我不能做的:

return new T();

此外,如果我想生成基于数据库值的代码我已经发现,在与T4模板结合使用Microsoft.SqlServer.Management.SMO一直在产生质量量的代码,而无需复制/粘贴或使用ReSharper的美妙。

很多的我与泛型中发现的问题,也就是我的冲击有很多的开发商谁不理解他们。当我做检查泛型的解决方案,但有时它变得复杂,因为C#的状态,你不能做一些事情,可能在我的脑海里似乎是顺理成章。

你有什么想法?你喜欢建立一个发电机,或做你喜欢使用泛型?此外,在多大程度上能泛型去?我知道泛型像样的数目,但也有陷阱和缺陷,我一直运行到这一事业我诉诸T4模板。

什么是你需要大量的灵活性来处理场景的更合适的方法是什么?哦,作为奖金这个问题,什么是C#和泛型?

好的资源
有帮助吗?

解决方案

可以做新T();如果你这样做

public class Meh<T>
  where T : new()
{
  public static T CreateOne()
  {
    return new T();
  }
}

作为用于代码发生器。我用一个每天都没有任何问题。我使用一个现在事实上: - )

泛型解决一个问题,代码发生器解决了另一个。例如,使用UML编辑器创建一个业务模型,然后用持久性代码生成你的班,因为我用做所有的时间此工具无法泛型来实现,因为每个持久类是完全不同的。

作为用于仿制药的良好来源。最好的一定是当然的乔恩斯基特的书! : - )

其他提示

由于T4的鼻祖,我已经好几次捍卫这个问题,你可以想像: - )

我的观点是,在其最好的代码生成是使用可重复使用的库产生等效值的方式的步骤。

正如许多其他人所说的,关键的概念,以保持DRY是永远,永远手动更改生成的代码,而是保留您在源元数据更改或者你发现的代码生成一个错误的再生能力。在这一点上生成的代码有很多的目标代码的特性,你就不会遇到复制/粘贴式的问题。

在一般情况下,它更以生产参数代码生成器(尤其是基于模板的系统)比它是正确的工程师高品质的基础库,下得使用成本同级别的努力,所以这是一个快速方式从一致性得到值,并删除重复的误差。

然而,我仍然相信,最终系统将最经常具有较少的总代码得到改善。如果不出意外,其内存占用量将几乎永远是显著更小(尽管人们倾向于认为免费仿制药的成本在这方面,他们大部分都不是的)。

如果您已经使用一个代码生成器实现一定的价值,那么这往往给你买了一些时间或金钱或商誉投资从生成的代码库中收获的库。然后,您可以逐步重新设计的代码生成器为目标的新的图书馆,并希望产生更少的代码。冲洗和重复。

这已经取得了我,在这个线程,来了一个有趣的对位是丰富的,复杂的,参数库不在学习曲线方面最容易的事情,尤其是对于那些不深深地沉浸在平台上。与代码生成粘到更简单的基本框架可以产生冗长的代码,但它往往是相当简单和容易阅读。

当然,你在你的产生有很多差异的极其丰富的参数,你可能只是交易掉复杂的产品在你的模板的复杂性。这是滑入并且可以使维护一样多头疼的一个简单的路径 - 注意这一点。

生成的代码是不是邪恶的,它没有气味!关键是产生在正确的时间正确的代码。我觉得T4是伟大的 - 我只是偶尔使用它,但是当我做到这一点是非常有帮助的。如果说,无条件,即生成的代码是坏的是无条件地疯狂!

在我看来,代码生成器都很好,只要代码生成是正常的构建过程的一部分,而不是运行一次,然后保持其输出的东西。我加入这个警告,因为如果只使用代码生成器一次,并丢弃创建它的数据,你只是自动创建一个巨大的干侵犯,维护头痛;而生成的代码每次都有效地意味着,无论使用的是做生成是真正的源代码,并将所生成的文件只是中间编译阶段,你应该大多忽略。

lex和yacc是允许你以有效的方式指定的功能,并从它产生高效率的代码的工具经典例子。尝试手工做他们的工作将延长开发时间,并可能产生更少的有效和更可读的代码。而当你当然可以包括像lex和yacc直接进入你的代码,并在运行时,而不是在编译的时候做自己的工作,那肯定会增加相当大的复杂性,将代码和慢下来。如果你确实需要在运行时更改您的规范它可能是值得的,但在使用的lex / yacc的产生在编译时你最代码通常情况下是一个巨大的胜利。

什么是Visual Studio 2010的一个很好的比例不会没有代码生成是可能的。实体框架是不可能的。拖放控制到窗体上的简单动作将是不可能的,也不会LINQ的。如果说,代码生成不应该用很奇怪,因为许多使用它,甚至没有考虑它。

也许这是有点苛刻,但对我的代码生成的气味。

这代码生成用于表示有其可以以“不要重复自己”的方式表达的众多潜在的共同原则。这可能需要更长的时间,但是当你最终只包含真正改变位类,基于包含力学的基础设施是令人满意的。

由于仿制药......不,我没有与它太多的问题。目前不工作的唯一的事情是说,

List<Animal> a = new List<Animal>();
List<object> o = a;

但即使这样,将有可能在C#的下一个版本。

更多代码意味着更多的复杂性。更多的复杂性意味着更多的地方对错误隐藏,这意味着更长的修复周期,这又意味着整个项目成本较高。

只要有可能,我更喜欢以最小化的代码的量,以提供等同的功能;理想地使用动态(编程)接近,而不是代码的生成。反射,属性方面和仿制药提供了大量的用于干战略选择,留下一代作为最后的手段。

代码生成,我在语言,框架等,发现了许多问题的解决方法,他们本身并不是邪恶的,我会说这是非常非常坏的(即邪恶)释放一种语言(C#)和框架,迫使你复制和粘贴(交换的属性,事件触发,缺乏宏),或使用神奇数字(WPF绑定)。

所以,我哭了,但我使用它们,因为我不得不这样做。

我已经用于代码生成T4和也泛型。两者都是良好的,具有它们的优点和缺点,并适合于不同的目的。

在我的情况下,我使用T4基于数据库模式,以产生实体,DAL和BLL。然而,DAL和BLL引用一个小型ORM我建立的基础上,泛型和反思。所以我觉得你可以一边使用他们身边,只要你保持控制并保持其小而简单。

T4生成静态代码,而泛型是动态的。如果使用泛型,您使用反射,据说这是比“硬编码”的解决方案少高性能。当然,你可以缓存反射的结果。

关于 “返回新T();”,我使用动态方法是这样的:

public class ObjectCreateMethod
    {
    delegate object MethodInvoker();
    MethodInvoker methodHandler = null;

    public ObjectCreateMethod(Type type)
    {
        CreateMethod(type.GetConstructor(Type.EmptyTypes));
    }

    public ObjectCreateMethod(ConstructorInfo target)
    {
        CreateMethod(target);
    }

    void CreateMethod(ConstructorInfo target)
    {
        DynamicMethod dynamic = new DynamicMethod(string.Empty,
                    typeof(object),
                    new Type[0],
                    target.DeclaringType);
        ILGenerator il = dynamic.GetILGenerator();
        il.DeclareLocal(target.DeclaringType);
        il.Emit(OpCodes.Newobj, target);
        il.Emit(OpCodes.Stloc_0);
        il.Emit(OpCodes.Ldloc_0);
        il.Emit(OpCodes.Ret);

        methodHandler = (MethodInvoker)dynamic.CreateDelegate(typeof(MethodInvoker));
    }

    public object CreateInstance()
    {
        return methodHandler();
    }
}

然后,我把它这样的:

ObjectCreateMethod _MetodoDinamico = new ObjectCreateMethod(info.PropertyType);
object _nuevaEntidad = _MetodoDinamico.CreateInstance();

泛型和代码生成是两个不同的东西。在某些情况下,你可以使用泛型,而不是代码生成,并为那些我相信你应该。对于其他情况下,代码生成是一个强大的工具。

有关,你只需要根据一些数据输入生成代码的所有情况下,代码生成是要走的路。最明显的,但绝不是唯一的例子是在Visual Studio中的表格编辑器。这里输入的是设计者数据和输出是代码。在这种情况下,仿制药实在是没有帮助的,但它是非常好的,这只是VS生成基于GUI的布局的代码。

代码生成器可以被认为是代码味道指示在目标的langauge一个缺陷或缺乏的功能。

例如,尽管已经在这里说,“是坚持不能一概而论对象”,这将是更好地认为它是“在C#中的对象,可以自动保持他们的数据不能在C#中推广”,因为我肯定可以在Python通过使用各种方法。

Python的方法可以,然而,在静态的语言通过使用操作符[](METHOD_NAME作为字符串),或者返回一个算符或字符串,这取决于要求的仿真。不幸的是该解决方案并不总是适用的,并返回一个函子可能是不方便的。

我提出的要点是,代码生成指示所选择的语言的一个缺陷是由在手为特定问题提供了更方便的专门语法处理。

的生成的代码的复制/粘贴型(如奥姆斯使)也可以是非常有用...

您可以创建数据库,然后具有ORM生成您喜欢的语言表示,数据库定义的副本。

在优势是,当你改变了最初的定义(数据库),按编译和ORM(如果你有一个很好的)可以重新生成您定义的副本。我们数据库中的所有引用可以通过编译器类型检查检查你的代码将失败,当你使用不存在了的表或列进行编译。

想一想:如果我调用方法几次在我的代码,我是不是指我把这一方法最初的名字吗?我一直在一遍又一遍地重复这个名字......语言的设计师认识到这个问题,并与“类型安全”的解决方案上来。如果不删除这些副本(干建议我们应该做的),但他们检查的正确性,而不是。

在ORM生成参照表和列名代码时所带来的相同溶液中。如果不删除这些拷贝/引用,但把数据库定义到您的(类型安全)的语言,你可以参考类和属性来代替。与编译器类型检查一起,这解决了以类似的方式类似的问题:保证编译时错误,而不是运行时那些当你指的是过时的或拼写错误表(类)或列(属性)

报价: 我还没有真正找到建立模板,可以说,例如实例自己的有效方法。 。换句话说我不能做的:

返回新T();

public abstract class MehBase<TSelf, TParam1, TParam2>
    where TSelf : MehBase<TSelf, TParam1, TParam2>, new()
{
    public static TSelf CreateOne()
    {
        return new TSelf();
    }
}

public class Meh<TParam1, TParam2> : MehBase<Meh<TParam1, TParam2>, TParam1, TParam2>
{
    public void Proof()
    {
        Meh<TParam1, TParam2> instanceOfSelf1 = Meh<TParam1, TParam2>.CreateOne();
        Meh<int, string> instanceOfSelf2 = Meh<int, string>.CreateOne();
    }
} 

代码生成,比如泛型,模板,和其它这样的快捷方式,是一个功能强大的工具。此外,与最强大的工具,它放大了用户良好的和邪恶的生产实力 - 他们不能分开

所以,如果你彻底了解你的代码生成器,预计一切会产生,为什么,并打算将它用于正当的理由这样做,那么有它。但不使用它(或任何其他技术),让你过去,你不是一个地方,知道在哪里你的方向,或如何到达那里。

有些人认为,如果你得到你目前的问题解决了,有些行为实现的,你是金色的。你在你的踪迹多少克鲁夫特和不透明留给下一个开发它并不总是很明显(这可能是你自己。)

为什么能够真正复制/粘贴,真快,使更多的接受吗?

这对代码生成,我可以看到的唯一理由。

即使发生器提供所有你所需要的灵活性,你还是要学会如何使用的灵活性 - 这是学习的又一层和测试所需

和即使它在零时间运行时,它仍然涨大的代码。

我推出我自己的数据访问类。它知道连接,事务,存储过程PARMS,等等等等一切,我只有一次写的所有东西ADO.NET。

它现在已经这么长时间,因为我不得不写(或甚至看)任何与它的连接对象,我会很难记住语法副手。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top