Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 代码生成器或T4模板,它们真的很邪恶吗?_C#_Generics_Code Generation_T4 - Fatal编程技术网

C# 代码生成器或T4模板,它们真的很邪恶吗?

C# 代码生成器或T4模板,它们真的很邪恶吗?,c#,generics,code-generation,t4,C#,Generics,Code Generation,T4,我听说有人说不应该使用代码生成器和T4模板。其背后的逻辑是,如果您使用生成器生成代码,那么有一种更有效的方法通过泛型和模板构建代码 虽然我稍微同意上面的说法,但我并没有真正找到有效的方法来构建模板,比如说实例化它们自己。换句话说,我永远也做不到: return new T(); 此外,如果我想基于数据库值生成代码,我发现将Microsoft.SqlServer.Management.SMO与T4模板结合使用,可以在不必复制/粘贴或使用resharper的情况下生成大量代码 我发现泛型也存在很多

我听说有人说不应该使用代码生成器和T4模板。其背后的逻辑是,如果您使用生成器生成代码,那么有一种更有效的方法通过泛型和模板构建代码

虽然我稍微同意上面的说法,但我并没有真正找到有效的方法来构建模板,比如说实例化它们自己。换句话说,我永远也做不到:

return new T();
此外,如果我想基于数据库值生成代码,我发现将
Microsoft.SqlServer.Management.SMO
与T4模板结合使用,可以在不必复制/粘贴或使用resharper的情况下生成大量代码

我发现泛型也存在很多问题,令我震惊的是,有很多开发人员不理解泛型。当我为一个解决方案检查泛型时,有时它会变得复杂,因为C#指出,在我看来,你不能做一些合乎逻辑的事情

你的想法是什么?您更喜欢构建生成器,还是更喜欢使用泛型?还有,泛型能走多远?我对泛型有相当多的了解,但我经常遇到一些陷阱和陷阱,导致我求助于T4模板

处理需要大量灵活性的场景时,哪种方法更合适?哦,这个问题的另一个好处是,关于C#和泛型的好资源是什么?

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

public class Meh<T>
  where T : new()
{
  public static T CreateOne()
  {
    return new T();
  }
}
公共类Meh
其中T:new()
{
公共静态T CreateOne()
{
返回新的T();
}
}
至于代码生成器。我每天都用一个,没有任何问题。事实上,我现在正在使用一个:-)

泛型解决一个问题,代码生成器解决另一个问题。例如,使用UML编辑器创建业务模型,然后像我一直使用的那样使用持久性代码生成类,这是泛型无法实现的,因为每个持久性类是完全不同的


关于泛型的一个好来源。最好的当然是!:-)

更多的代码意味着更复杂。更复杂意味着有更多的地方可以隐藏bug,这意味着更长的修复周期,这反过来意味着整个项目的成本更高


只要可能,我宁愿尽量减少代码量,以提供等效的功能;理想情况下使用动态(编程)方法,而不是代码生成。反射、属性、方面和泛型为干式策略提供了很多选择,将生成作为最后手段。

可能有点苛刻,但对我来说,代码生成有味道

使用代码生成意味着有许多基本的通用原则,可以用“不要重复自己”的方式来表达。这可能需要更长的时间,但当您最终得到只包含真正改变的位的类时,这是令人满意的,基于包含机制的基础结构

至于泛型……不,我没有太多问题。目前唯一不起作用的就是说

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

但是,即使在下一个版本的C#中,这也是可能的。

为什么能够非常非常快速地复制/粘贴,使它更容易被接受

这是我能看到的代码生成的唯一理由

即使生成器提供了您所需的所有灵活性,您仍然需要学习如何使用这种灵活性,这是需要学习和测试的另一个层次

即使它在零时间内运行,它仍然会使代码膨胀

我推出了自己的数据访问类。它知道关于连接、事务、存储过程参数等的一切,我只需编写一次ADO.NET的所有内容


我已经很久没有写(甚至没有看)任何包含连接对象的东西了,以至于我很难马上记住语法。

泛型和代码生成是两件不同的事情。在某些情况下,您可以使用泛型而不是代码生成,我认为您应该使用泛型。对于其他情况,代码生成是一个强大的工具


对于所有只需要根据某些数据输入生成代码的情况,代码生成是一种可行的方法。最明显但并非唯一的例子是VisualStudio中的表单编辑器。这里的输入是设计器数据,输出是代码。在这种情况下,泛型实际上没有任何帮助,但是VS仅仅根据GUI布局生成代码是非常好的

代码生成,如泛型、模板和其他此类快捷方式,是一个强大的工具。与最强大的工具一样,它放大了用户的善恶能力——它们是不可分割的

因此,如果您完全理解代码生成器,预测它将生成的所有内容,以及为什么,并打算让它出于合理的理由这样做,那么就要对它进行测试。但不要用它(或任何其他技巧)让你通过一个你不确定自己要去哪里或如何到达那里的地方


有些人认为,如果你解决了当前的问题,实施了一些行为,你就是黄金。你留给下一个开发人员(可能是你自己)的线索有多粗糙和不透明并不总是显而易见的。

生成代码不是坏事,也没有味道!关键是在正确的时间生成正确的代码。我认为T4很好——我只是偶尔使用它,但当我使用它时,它非常有用。无条件地说,生成代码是坏的是无条件地疯狂

在我看来,只要代码生成是正常构建过程的一部分,而不是只运行一次然后保留其输出,代码生成器就可以了。我添加这个警告是因为如果只使用一次代码生成器并丢弃
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();
    }
} 
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();