gpt4 book ai didi

c# - 是否可以在 ASP.NET MVC4 中将 C# 或 VB 函数标记为 Javascript 输出?

转载 作者:可可西里 更新时间:2023-11-01 02:44:50 31 4
gpt4 key购买 nike

我有一个 HtmlHelper 扩展方法,它将 javascript 回调函数作为参数。例如:

@Html.SomethingCool("containerName", "jsCallbackFunction")

<script type="javascript">
function jsCallbackFunction(e, i) {
alert(e.target.name + ' / ' + i);
}
</script>

如您所见,javascript 回调函数名称被传递给HtmlHelper 扩展方法。这导致开发人员不得不返回引用文档以找出 jsCallbackFunction 函数需要哪些参数。

我宁愿喜欢这样的东西:

@Html.SomethingCool("containerName", New SomethingCoolCallbackDelegate(Address Of jsCallbackFunction))

<OutputAsJavascript>
Private Sub jsCallbackFunction(e, i)
' SOMETHING goes here. some kind of html dom calls or ???
End Sub

SomethingCoolCallbackDelegate 将为目标函数提供代码契约。然后编译器会将 jsCallbackFunction 编译为 MVC 页面上的 javascript。

.NET 4/ASP.NET MVC 4/Razor 2 中是否内置了类似的东西?或者任何其他可以实现类似功能的技术?

示例在 VB 中,但 C# 中的解决方案也完全可以接受。

澄清:

@gideon:请注意jsCallbackFunction 有两个参数ei。但是,HtmlHelper 扩展方法只要求一个字符串(javascript 回调函数的名称),并没有指明此函数可能采用的参数。我试图解决的问题有两个方面。

  • 首先,缺少参数提示。代替“javascript 回调名称”字符串传递的 .NET 委托(delegate)类型将完成此操作。我愿意接受其他解决方案来实现这一目标。我知道 XML 注释。它们并不是真正的解决方案。

  • 其次,尝试让页面程序员使用单一语言工作。在 javascript 和 VB(或 js 和 C#)之间切换需要(至少对我而言)昂贵的上下文切换。我的大脑无法快速过渡。让我继续使用 VB 或 C# 工作效率更高且成本更低。因此,能够在 ASP.NET MVC/razor View 的上下文中使用 .NET 语言编写函数并将其编译为 javascript,这就是我在这里追求的目标。

@TyreeJackson:SomethingCool 是一个 HtmlHelper 扩展方法,我会编写它来输出 html 和 javascript。部分 javascript 输出需要调用用户(程序员)提供的函数来做出一些决定。将其想象成您提供给 ajax 调用的成功或失败函数。

最佳答案

虽然我无法为您提供完整的转译器/编译器选项,因为这将是一项巨大的工作量,但我可以提出以下建议,以协助智能感知支持以及函数和调用的发出。

这是基础设施代码。您需要完成 getArgumentLiteral 和 getConstantFromArgument 函数来处理您提出的其他情况,但这是一个不错的起点。

public abstract class JavascriptFunction<TFunction, TDelegate> where TFunction : JavascriptFunction<TFunction, TDelegate>, new()
{
private static TFunction instance = new TFunction();
private static string name = typeof(TFunction).Name;
private string functionBody;

protected JavascriptFunction(string functionBody) { this.functionBody = functionBody; }

public static string Call(Expression<Action<TDelegate>> func)
{
return instance.EmitFunctionCall(func);
}

public static string EmitFunction()
{
return "function " + name + "(" + extractParameterNames() + ")\r\n{\r\n " + instance.functionBody.Replace("\n", "\n ") + "\r\n}\r\n";
}

private string EmitFunctionCall(Expression<Action<TDelegate>> func)
{
return name + "(" + this.extractArgumentValues(((InvocationExpression) func.Body).Arguments) + ");";
}

private string extractArgumentValues(System.Collections.ObjectModel.ReadOnlyCollection<Expression> arguments)
{
System.Text.StringBuilder returnString = new System.Text.StringBuilder();
string commaOrBlank = "";
foreach(var argument in arguments)
{
returnString.Append(commaOrBlank + this.getArgumentLiteral(argument));
commaOrBlank = ", ";
}
return returnString.ToString();
}

private string getArgumentLiteral(Expression argument)
{
if (argument.NodeType == ExpressionType.Constant) return this.getConstantFromArgument((ConstantExpression) argument);
else return argument.ToString();
}

private string getConstantFromArgument(ConstantExpression constantExpression)
{
if (constantExpression.Type == typeof(String)) return "'" + constantExpression.Value.ToString().Replace("'", "\\'") + "'";
if (constantExpression.Type == typeof(Boolean)) return constantExpression.Value.ToString().ToLower();
return constantExpression.Value.ToString();
}

private static string extractParameterNames()
{
System.Text.StringBuilder returnString = new System.Text.StringBuilder();
string commaOrBlank = "";

MethodInfo method = typeof(TDelegate).GetMethod("Invoke");
foreach (ParameterInfo param in method.GetParameters())
{
returnString.Append(commaOrBlank + param.Name);
commaOrBlank = ", ";
}
return returnString.ToString();
}
}

public abstract class CoreJSFunction<TFunction, TDelegate> : JavascriptFunction<TFunction, TDelegate>
where TFunction : CoreJSFunction<TFunction, TDelegate>, new()
{
protected CoreJSFunction() : base(null) {}
}

这是一个标准函数支持包装器的示例:

public class alert : CoreJSFunction<alert, alert.signature>
{
public delegate void signature(string message);
}

这里有几个示例 Javascript 函数支持包装器:

public class hello : JavascriptFunction<hello, hello.signature>
{
public delegate void signature(string world, bool goodByeToo);
public hello() : base(@"return 'Hello ' + world + (goodByeToo ? '. And good bye too!' : ''") {}
}

public class bye : JavascriptFunction<bye, bye.signature>
{
public delegate void signature(string friends, bool bestOfLuck);
public bye() : base(@"return 'Bye ' + friends + (bestOfLuck ? '. And best of luck!' : ''") {}
}

这是一个控制台应用程序,展示了它的用途:

public class TestJavascriptFunctions
{
static void Main()
{
// TODO: Get javascript functions to emit to the client side somehow instead of writing them to the console
Console.WriteLine(hello.EmitFunction() + bye.EmitFunction());

// TODO: output calls to javascript function to the client side somehow instead of writing them to the console
Console.WriteLine(hello.Call(func=>func("Earth", false)));
Console.WriteLine(bye.Call(func=>func("Jane and John", true)));
Console.WriteLine(alert.Call(func=>func("Hello World!")));

Console.ReadKey();
}
}

这是控制台应用程序的输出:

function hello(world, goodByeToo)
{
return 'Hello ' + world + (goodByeToo ? '. And good bye too!' : ''
}
function bye(friends, bestOfLuck)
{
return 'Bye ' + friends + (bestOfLuck ? '. And best of luck!' : ''
}

hello('Earth', false);
bye('Jane and John', true);
alert('Hello World!');

更新:

您可能还想查看 JSIL .我与该项目无关,无法评价它的稳定性、准确性或有效性,但它听起来很有趣,并且可能会对您有所帮助。

关于c# - 是否可以在 ASP.NET MVC4 中将 C# 或 VB 函数标记为 Javascript 输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19760717/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com