Как определить и вызвать метод, помеченный атрибутом - PullRequest
3 голосов
/ 01 сентября 2011

Я хотел бы создать собственный атрибут для применения к любому методу в классе, а затем, вне этого класса, получить доступ к методу внутри класса, который был «помечен» атрибутом, чтобы вызвать метод с меткой как если бы это был делегат.

, например

public delegate string MethodCall( string args);

и

public class MethodAttribute : System.Attribute 
{
    public MethodCall callback;
    ...
}

и

class TypeWithCustomAttributesApplied {

    [Method]
    public string DelegateMethod(string args) {
        ...
    }
}

, а затем

void callMethods(string args) {
    TypeWithCustomAttributesApplied myObj = new TypeWithCustomAttributesApplied(); 
    DelegateMethod method = MyCustomerHelper.GetMarkedMethod(myObj)
    method(args);
}

или, возможно,

void callMethods(string args) {
    TypeWithCustomAttributesApplied myObj = new TypeWithCustomAttributesApplied(); 
    MethodAttribute methodAtrib = MyCustomerHelper.GetMarkedMethod(myObj)
    methodAtrib.callback(args);
}

В конечном итоге я пытаюсь добиться пользовательского атрибута, который я могу использовать для «пометки» точек входа Ajax в произвольных классах, а затем с помощью вспомогательного класса передать элемент управления «Ajax Enabled» помощнику, который определяет, какой метод в элементе управления для вызова и передает ему данные ajax от клиента. В любом случае, я не очень хорош с делегатами, но в целом я понимаю, как применять пользовательские атрибуты, но не уверен, как «захватить» метод, который я «помечаю»

Возможно, я мог бы справиться со своей задачей другим способом, но я пробую свои силы в атрибутах, поэтому я бы хотел, чтобы этот метод работал первым.


Мое окончательное решение:

public void CheckAjax(object anObject, string args)
    {
        MethodInfo[] methods = anObject.GetType().GetMethods();
        foreach (MethodInfo method in methods)
        {
            object[] attributes = method.GetCustomAttributes(true);

            bool containsAttribute = (from attribute in attributes
                                       where attribute is AjaxableAttribute
                                          select attribute).Count() > 0;

            if (containsAttribute)
            {
                string result_method = (string)method.Invoke(anObject, new object[] { args });
                Log.Write(string.Format("The Result from the method call was  {0} ", result_method));         
            }
        }         
    }

Ответы [ 4 ]

2 голосов
/ 01 сентября 2011

Вы можете использовать отражение и LINQ:

IEnumerable<MethodInfo> methods = myObj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(method => method.GetCustomAttributes(typeof(MethodAttribute), true).Length == 1).ToList();

string args = "some args";

foreach(MehtodInfo method in methods)
{
      method.Invoke(myObj, new object[] { args });
}
0 голосов
/ 01 сентября 2011

Как показано в другом месте, вы можете сделать

from m in type.GetMethods()
where m.GetCustomAttributes().OfType<YourAttribute>().Any()
select m

Как только вы получите MethodInfo с помощью отражения "GetMethods where has attribute", следующий код показывает, как вы создаете делегат на основе MethodInfo.В этом примере это какой-то Action<>, но это может быть другой тип.Здесь "parameterType" - это тип, предоставленный извне.Полученный делегат может быть приведен к нужному вам типу."target" - это экземпляр, к которому будет вызван этот делегат.

var fittingDelegateType = typeof(Action<>).MakeGenericType(parameterType);
var @delegate = Delegate.CreateDelegate(fittingDelegateType, target, info);
0 голосов
/ 01 сентября 2011

Что вы должны сделать, чтобы получить эти методы, это:

MethodInfo[] methods = typeof(TypeWithCustomAttributesApplied).GetMethods();
foreach (MethodInfo method in methods)
{
    object[] attributes = method.GetCustomeAttributes(true);

    bool containsAttribute = (from attribute in attributes
                               where attribute is MethodAttribute
                                  select attribute).Count() > 0;

    if (containsAttribute)
         // add attribute to list to return later
}

После возврата методов вы можете вызывать методы с помощью

method.Invoke(/* parameters *);

Надеюсь, это поможет.

0 голосов
/ 01 сентября 2011

Я думаю, что вашим решением для этого будет Reflection найти метод с нужным вам атрибутом.

...