如何在C#中应用代码的“模板”或“骨架”?

时间:2010-02-26 15:04:55

标签: c# reflection templates attributes

在我的业务层中,我需要许多遵循该模式的方法:

public BusinessClass PropertyName
{
    get
    {
        if (this.m_LocallyCachedValue == null)
        {
            if (this.Record == null)
            {
                this.m_LocallyCachedValue = new BusinessClass(
                     this.Database, this.PropertyId);
            }
            else
            {
                this.m_LocallyCachedValue = new BusinessClass(
                     this.Database, this.Record.ForeignKeyName);
            }
        }
        return this.m_LocallyCachedValue;
    }
}

我还在学习C#,我试图找出编写此模式的最佳方法,并将方法添加到遵循此模式的每个业务层类中,并替换正确的类型和变量名称。

BusinessClass是必须替换的typename,PropertyName,PropertyId,ForeignKeyName和m_LocallyCachedValue都是应该替换的变量。

属性是否可用?我需要反思吗?如何编写我在一个地方提供的骨架,然后只写一两行包含替换参数并获得传播模式?

编辑:修改了我误导性的标题 - 我希望找到一个不涉及代码生成或复制/粘贴技术的解决方案,而是能够在一些基类中编写一次代码的骨架形式,并将其“实例化”为许多子类作为各种属性的访问器。

编辑:这是我的解决方案,正如所建议的那样,但未被选定的回答者实施。

// I'll write many of these...
public BusinessClass PropertyName
{
    get
    {
        return GetSingleRelation(ref this.m_LocallyCachedValue, 
            this.PropertyId, "ForeignKeyName");
    }
}

// That all call this.
public TBusinessClass GetSingleRelation<TBusinessClass>(
    ref TBusinessClass cachedField, int fieldId, string contextFieldName)
{
    if (cachedField == null)
    {
        if (this.Record == null)
        {
            ConstructorInfo ci = typeof(TBusinessClass).GetConstructor(
                new Type[] { this.Database.GetType(), typeof(int) });
            cachedField = (TBusinessClass)ci.Invoke(
                new object[] { this.Database, fieldId });
        }
        else
        {
            var obj = this.Record.GetType().GetProperty(objName).GetValue(
                this.Record, null);
            ConstructorInfo ci = typeof(TBusinessClass).GetConstructor(
                new Type[] { this.Database.GetType(), obj.GetType()});
            cachedField = (TBusinessClass)ci.Invoke(
                new object[] { this.Database, obj });
        }
    }

    return cachedField;
}

3 个答案:

答案 0 :(得分:1)

结帐CodeSmith。他们有免费试用,如果你想购买它不是太贵。我已经使用它,它非常适合生成基于数据库的代码(这正是我猜你正在做的)。完成模板设置后,您可以随时重新生成代码。您可以直接从数据库模式中读取属性名称,也可以输入要使用的值。如果你想一次生成一整批类,我相信你甚至可以让它读取文件中的值。

答案 1 :(得分:1)

您可以使用T4模板查看。我不太确定哪个是T4的“资源”,但我在VisualStudioMagazine中找到了一个很好的article

它是免费的,具有易于使用的语法,并且实际上被许多项目(例如Subsonic)用于代码生成,因此您应该能够找到一些真实场景。

答案 2 :(得分:0)

您可以使用CodeSmith或MyGeneration等进行代码生成。您可能会在某处存储类和属性的列表,然后将该数据传递给代码生成器。在编译解决方案之前,您可能希望使用预构建事件来重新生成这些类。

或者,您可以将此功能烘焙到基类或辅助方法中。

public BusinessClass MyProperty
{
    get { return GetCached("MyProperty", "PropertyId", "FKName", "LocalValue"); }
}

我会将GetCached()的正文留给你,但它与你在参数中传入的变量基本相同。

如果某个类中的任何值对于类中的所有属性都相同,那么您当然可以从实例变量中提取它们,并且只传递给GetCached()那些因每个属性而异的东西。

底线:如果有办法将您正在做的事情的逻辑抽象为基本方法,那么使用该逻辑会成为一个单行,那么这可能是最好的方法,因为当你遇到特殊情况时,它更容易被覆盖。如果你不能这样做,代码生成可以为你做咕噜咕噜的工作,但你需要解决像这样的事情,我什么时候重新生成我如何重生< / em>等。