我在类中有多个方法实例,我需要快速调用和写入,而不将它们添加到我的main函数中。如何用属性完成?
e.g。 我有很多不同的类,有一个名为' invoke'的方法。我想添加一个我可以添加到此方法的自定义属性,然后在另一个名为' invoke all'的其他方法中调用每个类的invoke方法。
看起来像这样,但功能性。
public class main_class
{
public void invoke_all()
{
// call all the invokes
}
}
public class test1
{
[invoke]
public void invoke()
{
Console.WriteLine("test1 invoked");
}
}
public class test2
{
[invoke]
public void invoke()
{
Console.WriteLine("test2 invoked");
}
}
答案 0 :(得分:2)
要调用方法,您需要实例化一个类。要实例化类,您需要知道类型。
所以我们需要
Invoke
属性我们首先定义属性:
public class InvokeAttribute : Attribute
{
}
您可以使用此属性标记方法:
public class TestClass1
{
[Invoke]
public void Method1()
{
Console.WriteLine("TestClass1->Method1");
}
[Invoke]
public void Method2()
{
Console.WriteLine("TestClass1->Method2"););
}
}
public class TestClass2
{
[Invoke]
public void Method1()
{
Console.WriteLine("TestClass2->Method1");
}
}
现在如何找到并调用这些方法:
var methods = AppDomain.CurrentDomain.GetAssemblies() // Returns all currenlty loaded assemblies
.SelectMany(x => x.GetTypes()) // returns all types defined in this assemblies
.Where(x => x.IsClass) // only yields classes
.SelectMany(x => x.GetMethods()) // returns all methods defined in those classes
.Where(x => x.GetCustomAttributes(typeof(InvokeAttribute), false).FirstOrDefault() != null); // returns only methods that have the InvokeAttribute
foreach (var method in methods) // iterate through all found methods
{
var obj = Activator.CreateInstance(method.DeclaringType); // Instantiate the class
method.Invoke(obj, null); // invoke the method
}
上面的代码段将检查所有已加载的程序集。 linq查询
InvokeAttribute
这为我们提供了MethodInfo
的列表。方法信息包含DeclaringType
,它是声明方法的类。
我们可以使用Activator.CreateInstance
来实例化此类的对象。这仅在类具有不带参数的公共构造函数时才有效。
然后我们可以使用MethodInfo
在先前创建的类intance上调用该方法。这仅在方法没有参数时才有效。
答案 1 :(得分:1)
使用反射过程很简单:找到感兴趣的所有类型t
,从类型m
获取所有方法t
,然后为每个m
查找其自定义属性a
,如果集合a
包含您想要的属性,则调用该方法。
另见:
看起来像这样:
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (Type t in a.GetTypes())
{
// Skip types that don't have the [Invoke] attribute
var typeContainsInvokeAttribute = t.GetCustomAttributes(typeof(InvokeAttribute)).Any();
if (!typeContainsInvokeAttribute)
{
continue;
}
// This throws for types without a public, parameterless constructor
var instance = Activator.CreateInstance(t);
foreach (var methodInfo in instance.GetType().GetMethods())
{
var containsInvokeAttribute = methodInfo.GetCustomAttributes(typeof(InvokeAttribute)).Any();
if (containsInvokeAttribute)
{
methodInfo.Invoke(instance);
}
}
}
}
答案 2 :(得分:1)
您可以根据需要创建基于接口的解决方案。
我已经修改了你的代码并用这种方式实现了你想要的东西。
namespace ConsoleApplication1
{
public class main_class
{
static void Main(string[] args)
{
main_class.invoke_all();
}
public static void invoke_all()
{
// call all the invokes
// Help : https://stackoverflow.com/questions/26733/getting-all-types-that-implement-an-interface
foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
.Where(mytype => mytype.GetInterfaces().Contains(typeof(IInvokeAll))))
{
mytype.GetMethod("invoke").Invoke(Activator.CreateInstance(mytype, null), null);
}
//wait for user input
Console.ReadLine();
}
}
interface IInvokeAll
{
void invoke();
}
public class test1 : IInvokeAll
{
//[invoke]
public void invoke()
{
Console.WriteLine("test1 invoked");
}
}
public class test2 : IInvokeAll
{
//[invoke]
public void invoke()
{
Console.WriteLine("test2 invoked");
}
}
}
答案 3 :(得分:0)
对我来说有点不清楚,但我认为我有一个解决方案:
您无法直接执行您所要求的内容,但有解决方法 - 创建仅包含一种方法的界面:invoke
(或更多,如您所愿),主要方法,创建实现接口的对象列表 - 或者只创建一个字段并在该方法中使用它。然后,在简单的foreach
循环中,您可以对列表中的每个项目调用Invoke
方法(这将是可能的,因为它们实现了与该方法的接口)。
答案 4 :(得分:0)
您可以使用静态事件而不是属性
>> compose [(a) (b) (c)]
== [1 2 3 4 5 6 7 8 9 10 ]
在类构造函数中订阅此事件
public static class Events
{
public static event EventHandler OnInvoke;
public static void Run()
{
OnInvoke?.Invoke(null, EventArgs.Empty);
}
}
但请勿忘记取消订阅此活动否则您的所有物品将永远不会被处置
这将在应用程序中的每个实例化(现有)对象上调用您的代码。表示如果您有两个public class Customer
{
public Customer()
{
Events.OnInvoke += (sender, args) => Call();
}
}
类型的对象将比test1
执行两次
答案 5 :(得分:-2)
这是一个示例代码,用于实现您希望使用委托的内容。
public class main_class
{
private static main_class instance;
public delegate void MethodInvoker();
public MethodInvoker MyInvoker { get; set; }
public static main_class Instance
{
get
{
if (instance == null)
{
instance = new main_class();
}
return instance;
}
}
private main_class() { }
public void invoke_all()
{
MyInvoker();
}
}
public class test1
{
public test1()
{
main_class.Instance.MyInvoker += invoke;
}
public void invoke()
{
Console.WriteLine("test1 invoked");
}
}
public class test2
{
public test2()
{
main_class.Instance.MyInvoker += invoke;
}
public void invoke()
{
Console.WriteLine("test2 invoked");
}
}
现在,只要你调用main_class.Instance.invoke_all();
,它就会调用所有方法。