প্রতিবিম্ব সহ স্থির পদ্ধতিতে কল করুন


111

নেমস্পেসে mySolution.Macrosযেমন আমার বেশ কয়েকটি স্ট্যাটিক ক্লাস রয়েছে

static class Indent{    
     public static void Run(){
         // implementation
     }
     // other helper methods
}

সুতরাং আমার প্রশ্নটি প্রতিবিম্বের সাহায্যে কীভাবে এই পদ্ধতিগুলি কল করা সম্ভব হবে?

যদি পদ্ধতিগুলি স্থির না হয় তবে আমি এর মতো কিছু করতে পারি:

var macroClasses = Assembly.GetExecutingAssembly().GetTypes().Where( x => x.Namespace.ToUpper().Contains("MACRO") );

foreach (var tempClass in macroClasses)
{
   var curInsance = Activator.CreateInstance(tempClass);
   // I know have an instance of a macro and will be able to run it

   // using reflection I will be able to run the method as:
   curInsance.GetType().GetMethod("Run").Invoke(curInsance, null);
}

আমি আমার ক্লাসগুলি স্থির রাখতে চাই। স্থির পদ্ধতিগুলির সাথে আমি কীভাবে অনুরূপ কিছু করতে সক্ষম হব?

সংক্ষেপে আমি নাম স্থলে মাই সলিউশন.ম্যাক্রোসে থাকা সমস্ত স্থিতিশীল শ্রেণীর সমস্ত রান পদ্ধতিতে কল করতে চাই।

উত্তর:


150

হিসাবে MethodInfo.Invoke ডকুমেন্টেশন রাজ্যের প্রথম আর্গুমেন্ট স্ট্যাটিক পদ্ধতি জন্য উপেক্ষা করা হয় তাই আপনি শুধু নাল পাস করতে পারেন।

foreach (var tempClass in macroClasses)
{
   // using reflection I will be able to run the method as:
   tempClass.GetMethod("Run").Invoke(null, null);
}

মতামতটি উল্লেখ করেছে, আপনি ফোন করার সময় পদ্ধতিটি স্থির রয়েছে তা নিশ্চিত করতে চাইতে পারেন GetMethod:

tempClass.GetMethod("Run", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);

4
আপনি কিছু বাঁধাই পতাকা পাস করতে চাইতে পারেন GetMethod
ড্যানিয়েল এ হোয়াইট

2
BindingFlags.Staticআপনি ছাড়া পদ্ধতিটি সফলভাবে প্রথম স্থানে নাও পেতে পারেন ...
এরিক

1
পদ্ধতিটি যদি কোনও পূর্বপুরুষের ক্লাসে থাকে তবে আপনি বাইন্ডিংফ্ল্যাজগুলি যোগ করতে পারেন F
জে ওউওহ্যান্ড

20

আপনি একবারে ডেলিগেট তৈরির মূল্য প্রদানের মাধ্যমে সত্যই, সত্যই, সত্যই আপনার কোডটিকে অনেক অনুকূল করতে পারেন (স্ট্যাটিক পদ্ধতিতে কল করার জন্য ক্লাসটি ইনস্ট্যান্ট করারও দরকার নেই)। আমি খুব অনুরূপ কিছু করেছি এবং আমি কেবল একজন সহায়ক শ্রেণীর সাহায্যে "রান" পদ্ধতিতে একটি প্রতিনিধিকে ক্যাশে করেছি :-)। দেখে মনে হচ্ছে:

static class Indent{    
     public static void Run(){
         // implementation
     }
     // other helper methods
}

static class MacroRunner {

    static MacroRunner() {
        BuildMacroRunnerList();
    }

    static void BuildMacroRunnerList() {
        macroRunners = System.Reflection.Assembly.GetExecutingAssembly()
            .GetTypes()
            .Where(x => x.Namespace.ToUpper().Contains("MACRO"))
            .Select(t => (Action)Delegate.CreateDelegate(
                typeof(Action), 
                null, 
                t.GetMethod("Run", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
            .ToList();
    }

    static List<Action> macroRunners;

    public static void Run() {
        foreach(var run in macroRunners)
            run();
    }
}

এটি এইভাবে অনেক দ্রুত।

যদি আপনার পদ্ধতির স্বাক্ষর অ্যাকশন থেকে পৃথক হয় তবে আপনি টাইপ-কাস্ট এবং টাইপফুলকে অ্যাকশন থেকে প্রয়োজনীয় কোনও অ্যাকশন এবং ফানক জেনেরিক ধরণের প্রতিস্থাপন করতে পারেন, বা আপনার ডেলিগেট ঘোষণা এবং ব্যবহার করতে পারেন। আমার নিজস্ব বাস্তবায়ন সুন্দর মুদ্রণ অবজেক্টগুলিতে ফানক ব্যবহার করে:

static class PrettyPrinter {

    static PrettyPrinter() {
        BuildPrettyPrinterList();
    }

    static void BuildPrettyPrinterList() {
        printers = System.Reflection.Assembly.GetExecutingAssembly()
            .GetTypes()
            .Where(x => x.Name.EndsWith("PrettyPrinter"))
            .Select(t => (Func<object, string>)Delegate.CreateDelegate(
                typeof(Func<object, string>), 
                null, 
                t.GetMethod("Print", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
            .ToList();
    }

    static List<Func<object, string>> printers;

    public static void Print(object obj) {
        foreach(var printer in printers)
            print(obj);
    }
}

0

আমি সরলতা পছন্দ করি ...

private void _InvokeNamespaceClassesStaticMethod(string namespaceName, string methodName, params object[] parameters) {
    foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) {
        foreach(var _t in _a.GetTypes()) {
            try {
                if((_t.Namespace == namespaceName) && _t.IsClass) _t.GetMethod(methodName, (BindingFlags.Static | BindingFlags.Public))?.Invoke(null, parameters);
            } catch { }
        }
    }
}

ব্যবহারের ...

    _InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run");

তবে আপনি যদি ব্যতিক্রমগুলি সামলানো সহ আরও কিছু শক্তিশালী কিছু খুঁজছেন ...

private InvokeNamespaceClassStaticMethodResult[] _InvokeNamespaceClassStaticMethod(string namespaceName, string methodName, bool throwExceptions, params object[] parameters) {
    var results = new List<InvokeNamespaceClassStaticMethodResult>();
    foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) {
        foreach(var _t in _a.GetTypes()) {
            if((_t.Namespace == namespaceName) && _t.IsClass) {
                var method_t = _t.GetMethod(methodName, parameters.Select(_ => _.GetType()).ToArray());
                if((method_t != null) && method_t.IsPublic && method_t.IsStatic) {
                    var details_t = new InvokeNamespaceClassStaticMethodResult();
                    details_t.Namespace = _t.Namespace;
                    details_t.Class = _t.Name;
                    details_t.Method = method_t.Name;
                    try {
                        if(method_t.ReturnType == typeof(void)) {
                            method_t.Invoke(null, parameters);
                            details_t.Void = true;
                        } else {
                            details_t.Return = method_t.Invoke(null, parameters);
                        }
                    } catch(Exception ex) {
                        if(throwExceptions) {
                            throw;
                        } else {
                            details_t.Exception = ex;
                        }
                    }
                    results.Add(details_t);
                }
            }
        }
    }
    return results.ToArray();
}

private class InvokeNamespaceClassStaticMethodResult {
    public string Namespace;
    public string Class;
    public string Method;
    public object Return;
    public bool Void;
    public Exception Exception;
}

ব্যবহার প্রায় একই রকম ...

_InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run", false);

2
যে কোনও সম্ভাব্য ব্যতিক্রম গ্রাস করা সাধারণত একটি খারাপ ধারণা।
ডি স্ট্যানলি

সত্য। এটা অলস কিন্তু সহজ ছিল। আমি আমার উত্তর উন্নত করেছি।
ডায়নামিকেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.