Если вам нужен только фиксированный тип делегата с именованными параметрами, вы можете просто определить свой собственный тип делегата:
Func просто определен так:
public delegate TResult Func<in T, out TResult>(T arg)
Таким образом, вы можете определить свой собственный тип делегата с желаемым параметром.
Но в вашем примере вы хотите сохранить переданный тип делегата, поэтому здесь это не работает. Теоретически вы можете определить свою функцию следующим образом:
public static T Extend(T functionToWrap)
{
}
К сожалению, нет хороших общих ограничений, которые ограничивают тип ввода делегатом с правильной подписью (или даже просто делегатами). Но без этих ограничений реализация станет настолько уродливой, и вы потеряете столько статической безопасности типов, что IMO не стоит этого.
Один обходной путь использует:
new MyFunc(Extend(f))
где MyFunc определяет нужные имена параметров.
Или вы можете сделать следующее:
public static T ConvertDelegate<T>(Delegate d)
{
if (!(typeof(T).IsSubclassOf(typeof(Delegate))))
throw new ArgumentException("T is no Delegate");
if (d == null)
throw new ArgumentNullException();
MulticastDelegate md = d as MulticastDelegate;
Delegate[] invList = null;
int invCount = 1;
if (md != null)
invList = md.GetInvocationList();
if (invList != null)
invCount = invList.Length;
if (invCount == 1)
{
return (T)(object)Delegate.CreateDelegate(typeof(T), d.Target, d.Method);
}
else
{
for (int i = 0; i < invList.Length; i++)
{
invList[i] = (Delegate)(object)ConvertDelegate<T>(invList[i]);
}
return (T)(object)MulticastDelegate.Combine(invList);
}
}
public static TDelegate Extend<TDelegate,TArg,TResult>(Func<TArg,TResult> functionToWrap)
where TDelegate:class
{
Func<TArg,TResult> wrappedFunc= DoTheWrapping(functionToWrap);
return ConvertDelegate<TDelegate>(wrappedFunc);
}
Кстати, функцию ConvertDelegate можно использовать для получения Co / Contravariance для делегатов даже до .net 4.