C# razor引擎模板中的类

C# razor引擎模板中的类,c#,razor,C#,Razor,是否可以在模板中创建类?类似于 @{ public class MyClass { public MyClass() { Three = new List<string>(); } public string One { get; set; } public int Two { get; set; } public List<string> Three { g

是否可以在模板中创建类?类似于

@{
    public class MyClass {
        public MyClass() {
            Three = new List<string>();
        }

        public string One { get; set; }
        public int Two { get; set; }
        public List<string> Three { get; set; }
    }
}
@{
公共类MyClass{
公共MyClass(){
三=新列表();
}
公共字符串One{get;set;}
公共整数二{get;set;}
公共列表三{get;set;}
}
}

当前,当我尝试执行此操作时,会出现“无法编译模板。请查看错误列表了解详细信息”。我希望获取XML内容并使用XmlSerializer在模板中创建MyClass的实例。我无法先进行反序列化并将其推入模型中,因为类可能会因模板而异。

我建议使用特定的ViewModel类,该类可能具有动态属性(ExpandooObject)允许您根据需要使用任何自定义数据结构填充它,同时仍然为视图可能需要的任何其他内容进行强类型通信


这也使您的视图模型与视图本身分开,这是一种很好的做法(html和代码在可读性问题上混合得不太好)。

我将在这里发布我的回复:

我不确定这目前是否可行。当您使用代码块(@{})时,您实际上是在一个方法中编写代码,例如,您上面的代码将执行以下操作:

public void Execute()
{
    this.Clear();
    public class MyClass {
        public MyClass() {
            Three = new List<string>();
        }

        public string One { get; set; }
        public int Two { get; set; }
        public List<string> Three { get; set;}
    }
}
public void Execute()
{
这个.Clear();
公共类MyClass{
公共MyClass(){
三=新列表();
}
公共字符串One{get;set;}
公共整数二{get;set;}
公共列表三{get;set;}
}
}
…当然,这是无效的。您将面临的另一个问题是,要使用xml序列化/反序列化,类型必须是已知的,但是如果您在模板本身中定义类型,那么首先如何对其进行反序列化呢

您可以做的是使用自定义基础模板:

public class CustomTemplateBase<T> : TemplateBase<T>
{
    public dynamic Instance { get; set; }

    public dynamic CreateInstance(string typeName)
    {
        Type type = Type.GetType(typeName);

        // You'd to your deserialisation here, I'm going to
        // just cheat and return a new instance.
        return Activator.CreateInstance(type);
    }
}
公共类CustomTemplateBase:TemplateBase
{
公共动态实例{get;set;}
公共动态CreateInstance(字符串类型名称)
{
Type Type=Type.GetType(typeName);
//你要在这里进行反序列化,我要
//只需作弊并返回一个新实例。
返回Activator.CreateInstance(类型);
}
}
通过使用动态属性和动态返回类型,我们定义了一个方法,该方法将允许我们创建一个实例(通过激活或反序列化等)并对其调用成员访问。要在模板中使用,您可以执行以下操作:

@{
  Instance = CreateInstance("ConsoleApplication1.MyClass, ConsoleApplication1");
  Instance.One = "Hello World";
}
<h1>@Instance.One</h1>
@{
Instance=CreateInstance(“ConsoleApplication1.MyClass,ConsoleApplication1”);
Instance.One=“你好,世界”;
}
@一个例子

其中“MyClass”是在我的应用程序中的某个地方定义的。重要的是,我正在为每个模板创建一个实例。

是的,这是完全可能的。使用
@functions
关键字:

@functions {
    public class MyClass {
        public MyClass() {
            Three = new List<string>();
        }

        public string One { get; set; }
        public int Two { get; set; }
        public List<string> Three { get; set; }
    }
}
@函数{
公共类MyClass{
公共MyClass(){
三=新列表();
}
公共字符串One{get;set;}
公共整数二{get;set;}
公共列表三{get;set;}
}
}

如果可以的话,这会不会完全绕开一开始就有模型/视图/控制器的想法?你不能把
MyClass
放在一个单独的文件中吗?好的,每个模板有2个文件,但它会起作用。你能取消选中“答案”并改为选中“Kirk Woll”答案吗,因为这是正确的答案。这是否是一个好主意,有待讨论,但这确实回答了问题,请投我一票。(Ans由于我只能编辑解决方案中的视图,这就是我所需要的;尽管有代码气味)这非常适合于您希望创建中间转换类型但不希望使用匿名类型的情况,因为您无法将这些类型传递给razor帮助器。遗憾的是,像Umbraco这样的平台不能很好地使用代码密集型方法。如果您的控制器完全能够将所有必需的转换执行为更具体的ViewModel.upvote,我不会经常这样做。在一个更大的项目上,你通常不会这么做,但在普通的小型网络矩阵的东西上,这会更聪明、更容易。为什么会有这么多自鸣得意的bug?投票赞成@DarcyThomas和其他人的保留意见/评论。谢谢。这对测试非常有用。