我正在尝试创建一个类似于asp mvc中的url构建器,除了我们的方法经常更改参数和破坏页面。
有没有人知道是否有可能强制c#允许从这样的委托中返回类似语法的事件:
new UrlBuilder2<FakeController>(x => { return x.ActionWithInt; });
这个课程类似于:
public class UrlBuilder<TController>
{
public UrlBuilder2(Func<TController, TType> action)
{
}
}
基本上我想知道TType使用什么类型。或者如果可能的话。
编辑 -
我会(如果可能的话)喜欢只使用方法,类似于分配事件的方式(clickEvent =+ myMethod;
)
答案 0 :(得分:1)
不完全确定您想要实现的目标,但假设您想要生成链接simlar:
MyForm/MyMethod.aspx
基于WebForm(或任何其他类),如下所示:
public class MyForm {
public void MyMethod() {
// Something here
}
public void MethodWithParams(int i, string str) {
// Something here
}
}
您可以使用此构建器(包含测试):
class UrlBuilder2<T> {
private readonly Expression<Func<T, object>> callExpression;
public UrlBuilder2(Expression<Func<T,object>> callExpression) {
this.callExpression = callExpression;
}
public override string ToString() {
MethodCallExpression call = (MethodCallExpression) callExpression.Body;
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}/{1}.aspx", call.Object.Type.Name, call.Method.Name);
var delimiter = "?";
var formalParams = call.Method.GetParameters();
for (int i = 0; i < formalParams.Length; i++) {
var actual = call.Arguments[i];
if (actual == null)
continue; // Do not put NULL to QueryString
var formal = formalParams[i].Name;
sb.AppendFormat("{0}{1}={2}", delimiter, formal, HttpUtility.HtmlEncode(actual.ToString()));
}
return sb.ToString();
}
}
[Test]
public void CanBuildUrlByClassAndMethodName() {
var str = new UrlBuilder2<MyForm>(c => c.MyMethod()).ToString();
str.Should().Be.EqualTo("MyForm/MyMethod.aspx");
}
[Test]
public void CanBuildUrlByMethodWithParams() {
var str = new UrlBuilder2<MyForm>(c => c.MethodWithParams(2, "hello")).ToString();
str.Should().Be.EqualTo("MyForm/MyMethod.aspx?i=2&str=hello");
}
所有这些都可以让你保持链接类型安全,并且可以利用重构优势 您可能需要增强UrlBuilder2,但这应该可以帮助您入门。
如果您只想使用方法名称来生成链接,可以执行以下操作:
class MyClass {
public void MyMethod() {}
}
class UrlBuilder3<T> {
Expression<Func<T, Action>> info;
public UrlBuilder3(Expression<Func<T, Action>> info) {
this.info = info;
}
public override string ToString() {
UnaryExpression exp = (UnaryExpression)info.Body;
MethodCallExpression createDelegate = (MethodCallExpression)exp.Operand;
// 0-Action,1-x,2-Delegate as Constant
ConstantExpression methodArgument = (ConstantExpression)createDelegate.Arguments[2];
MethodInfo method = (MethodInfo)methodArgument.Value;
return string.Format("{0}/{1}.aspx", typeof(T).Name, method.Name);
}
}
[Test]
public void UrlByDelegate() {
new UrlBuilder3<MyClass>(x => x.MyMethod).ToString()
.Should().Be.EqualTo("MyClass/MyMethod.aspx");
}
棘手的是正确解析表达式树。上面的代码适用于此特定示例,但您需要检查它是否适用于您的所有情况。
答案 1 :(得分:0)
您可以返回一个函数指针,也就是c#中的委托,如下所示。
public delegate int mydelegate(string s);
public class Test
{
mydelegate MyFunc(string s)
{
return (astring => astring.Length + s.Length);
}
}
这将允许您将函数的输出附加到事件。
var test = new Test();
someevent += test.MyFunc("this is a test");
假设someevent采用了与委托具有相同签名的函数。