সি # তে রানটাইমের সময় ডিএলএল লোড হচ্ছে


91

আমি কীভাবে আপনি একটি সি # অ্যাপ্লিকেশনটির অভ্যন্তরে রান টাইমে .dll আমদানি করতে এবং ব্যবহার করতে যেতে পারেন তা নির্ধারণ করার চেষ্টা করছি। এসেম্বলি.ল্ডফিল () ব্যবহার করে আমি আমার প্রোগ্রামটি ডিএল লোড করার জন্য পরিচালিত হয়েছি (এই অংশটি অবশ্যই কাজ করছে কারণ আমি টসস্ট্রিং ()) দিয়ে ক্লাসের নাম পেতে সক্ষম হয়েছি, তবে আমি 'আউটপুট' ব্যবহার করতে অক্ষম আমার কনসোল অ্যাপ্লিকেশন ভিতরে থেকে পদ্ধতি। আমি .dll সংকলন করছি তারপরে এটিকে আমার কনসোলের প্রকল্পে নিয়ে যাচ্ছি। ক্রিয়েটইনস্ট্যান্স এবং তারপরে পদ্ধতিগুলি ব্যবহার করতে সক্ষম হওয়ার মধ্যে কি কোনও অতিরিক্ত পদক্ষেপ রয়েছে?

এটি আমার ডিএলএল এর ক্লাস:

namespace DLL
{
    using System;

    public class Class1
    {
        public void Output(string s)
        {
            Console.WriteLine(s);
        }
    }
}

এবং আমি অ্যাপ্লিকেশনটি আমি ডিএলএল লোড করতে চাই

namespace ConsoleApplication1
{
    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                var c = Activator.CreateInstance(type);
                c.Output(@"Hello");
            }

            Console.ReadLine();
        }
    }
}

উত্তর:


128

সদস্যদের সরাসরি সি # থেকে কল করার জন্য সংকলনের সময়ে সমাধানযোগ্য হতে হবে। অন্যথায় আপনাকে অবশ্যই প্রতিবিম্ব বা গতিশীল অবজেক্ট ব্যবহার করতে হবে।

প্রতিবিম্ব

namespace ConsoleApplication1
{
    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                var c = Activator.CreateInstance(type);
                type.InvokeMember("Output", BindingFlags.InvokeMethod, null, c, new object[] {@"Hello"});
            }

            Console.ReadLine();
        }
    }
}

গতিশীল (। নেট 4.0)

namespace ConsoleApplication1
{
    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                dynamic c = Activator.CreateInstance(type);
                c.Output(@"Hello");
            }

            Console.ReadLine();
        }
    }
}

12
নোট করুন যে Outputএটি সমাবেশে প্রতিটি ধরণের প্রতিবাদ করার চেষ্টা করে, যা সম্ভবত "ডান" শ্রেণীর সন্ধানের আগে নিক্ষেপ করবে ...
রিড কপসি

4
@ রিডকপসি, সম্মত, তবে তার সাধারণ উদাহরণের জন্য, তাঁর ধরণটি কেবলমাত্র দৃশ্যমান। "কোনও সমাবেশের বাইরে দৃশ্যমান একমাত্র প্রকারগুলি হ'ল জনসাধারণ এবং প্রকারের মধ্যে অন্যান্য পাবলিক প্রকারের মধ্যে বাসা বাঁধে" " একটি তুচ্ছ উদাহরণের জন্য, স্পষ্টতই এটি একটি সমস্যা হবে ...
ডার্ক ফ্যালকন

4
দু'টি উদাহরণ দিয়ে ঝরঝরে! :)
নীলস অ্যাবিল্ডগার্ড

22
এ কারণেই ইন্টারফেসগুলি প্রায়শই ব্যবহৃত হয় এবং আপনি বৈশিষ্ট্য সনাক্তকরণ যেমন IDog dog = someInstance as IDog;এটি শূন্য না হলে পরীক্ষা করতে পারেন। আপনার ইন্টারফেসগুলি ক্লায়েন্টদের দ্বারা ভাগ করা একটি সাধারণ ডিএলএলতে রাখুন এবং গতিশীলভাবে লোড হওয়া কোনও প্লাগইন অবশ্যই সেই ইন্টারফেসটি প্রয়োগ করতে হবে। এটি আপনাকে আইডোগ ইন্টারফেসের বিপরীতে আপনার ক্লায়েন্টকে কোড করতে দেয় এবং গতিশীল ব্যবহারের পরিবর্তে সংকলন সময়ে ইন্টেলিজেন্স + স্ট্রং টাইপ চেকিং করতে দেয়।
অ্যারোনএলএস

4
@ তারেক.এমএইচ: এর জন্য একটি সংকলন-সময় নির্ভরতা দরকার Class1। এই মুহুর্তে আপনি কেবল ব্যবহার করতে পারেন new Class1()। প্রশ্নকারী স্পষ্টভাবে একটি রানটাইম নির্ভরতা নির্দিষ্ট করে দিয়েছে। dynamicপ্রোগ্রামটি মোটেও একটি সংকলন-সময় নির্ভরতা প্রয়োজন না করার অনুমতি দেয় Class1
ফ্যালকন

39

এখনই, আপনি সমাবেশে সংজ্ঞায়িত প্রতিটি ধরণের একটি উদাহরণ তৈরি করছেন । Class1পদ্ধতিটি কল করার জন্য আপনার কেবলমাত্র একটি একক দৃষ্টান্ত তৈরি করতে হবে:

class Program
{
    static void Main(string[] args)
    {
        var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

        var theType = DLL.GetType("DLL.Class1");
        var c = Activator.CreateInstance(theType);
        var method = theType.GetMethod("Output");
        method.Invoke(c, new object[]{@"Hello"});

        Console.ReadLine();
    }
}

19

Outputপদ্ধতিটি প্রকাশ করে এমন ধরণের একটি উদাহরণ আপনাকে তৈরি করতে হবে :

static void Main(string[] args)
    {
        var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

        var class1Type = DLL.GetType("DLL.Class1");

        //Now you can use reflection or dynamic to call the method. I will show you the dynamic way

        dynamic c = Activator.CreateInstance(class1Type);
        c.Output(@"Hello");

        Console.ReadLine();
     }

আপনাকে অনেক ধন্যবাদ - আমি ঠিক এটিই খুঁজছি। আমি এটি বিশ্বাস করতে পারি না যে এটি অন্যান্য উত্তরগুলির চেয়ে উচ্চতর রেটযুক্ত নয়, কারণ এটি গতিশীল কীওয়ার্ডটির ব্যবহার দেখায়।
skiphoppy

আহ, এখন আমি এটি ডার্কফালকনের জবাবতেও দেখছি। যদিও আপনার চেয়ে কম ছিল এবং এটি দেখতে সহজ হয়েছে। :)
skiphoppy

0

Activator.CreateInstance() একটি অবজেক্ট প্রদান করে, যার কোনও আউটপুট পদ্ধতি নেই।

দেখে মনে হচ্ছে আপনি ডায়নামিক প্রোগ্রামিং ভাষা থেকে এসেছেন? সি # অবশ্যই তা নয় এবং আপনি যা করার চেষ্টা করছেন তা কঠিন হবে।

যেহেতু আপনি একটি নির্দিষ্ট স্থান থেকে একটি নির্দিষ্ট dll লোড করছেন, তাই আপনি কেবল এটি আপনার কনসোল অ্যাপ্লিকেশনটির রেফারেন্স হিসাবে যুক্ত করতে চান?

আপনি যদি পুরোপুরি এর মাধ্যমে সমাবেশটি লোড করতে চান তবে আপনাকে Assembly.Loadকোনও সদস্যকে কল করতে প্রতিবিম্বের মধ্য দিয়ে যেতে হবেc

এর মতো কিছু করা type.GetMethod("Output").Invoke(c, null);উচিত।


0
foreach (var f in Directory.GetFiles(".", "*.dll"))
            Assembly.LoadFrom(f);

এটি আপনার এক্সিকিউটেবলের ফোল্ডারে উপস্থিত সমস্ত ডিএলএল লোড করে।

আমার ক্ষেত্রে আমি Reflectionক্লাসের সমস্ত সাবক্লাস, এমনকি অন্যান্য ডিএলএল-তেও অনুসন্ধান করার চেষ্টা করছিলাম । এটি কার্যকর হয়েছে, তবে এটি করার সর্বোত্তম উপায় কিনা তা আমি নিশ্চিত নই।

সম্পাদনা: আমি এটির সময়সীমা নিয়ে এসেছি এবং এগুলি কেবল প্রথমবারের মতো লোড হবে বলে মনে হচ্ছে।

Stopwatch stopwatch = new Stopwatch();
for (int i = 0; i < 4; i++)
{
    stopwatch.Restart();
    foreach (var f in Directory.GetFiles(".", "*.dll"))
        Assembly.LoadFrom(f);
    stopwatch.Stop();
    Console.WriteLine(stopwatch.ElapsedMilliseconds);
}

আউটপুট: 34 0 0 0

সুতরাং যে কোনও প্রতিচ্ছবি সন্ধানের আগে কোনওটি সেই কোডটি চালাতে পারে।


-1

এটি এতটা কঠিন নয়।

আপনি লোড হওয়া অবজেক্টের উপলব্ধ ক্রিয়াকলাপগুলি পরীক্ষা করতে পারেন এবং আপনি নাম অনুসারে যা সন্ধান করছেন তা যদি খুঁজে পান তবে তার প্রত্যাশিত পারমগুলি স্নুপ করুন any যদি আপনি যে কলটি সন্ধান করার চেষ্টা করছেন এটি যদি তা হয়ে থাকে তবে মেথথইনফো অবজেক্টের ইনভোক পদ্ধতিটি ব্যবহার করে এটি কল করুন।

অন্য বিকল্পটি হ'ল কেবল আপনার বাহ্যিক অবজেক্টগুলিকে ইন্টারফেসে তৈরি করা, এবং বোঝা বস্তুটিকে সেই ইন্টারফেসে কাস্ট করা। যদি সফল হয় তবে ফাংশনটি দেশীয়ভাবে কল করুন।

এটি বেশ সহজ জিনিস।


বাহ, ডাউন-ভোট কেন তা নিশ্চিত নয়। আমার কাছে গত 12 বছরের মতো একটি প্রযোজনার অ্যাপ্লিকেশন রয়েছে। * শ্রাগ * কারও কাছে এটি করতে কিছু কোড দরকার, আমাকে একটি বার্তা শুট করুন। আমি আমার প্রোডাকশন কোডের কিছু অংশ প্যাকেজ করব এবং এটি প্রেরণ করব।
ক্রিসএইচ

10
আমি সন্দেহ করি যে ডাউনভোটদের উদাহরণের ঘাটতি এবং ঘনীভূত সুরের সাথে করণীয় হবে ... মনে হচ্ছে আপনার কাছে যদিও পুরো উত্তরের ভিত্তি রয়েছে, সুতরাং আরও বিশদে সম্পাদনা করতে ভয় পাবেন না :)
শেডো

4
"এটি বেশ সহজ সরল স্টাফ" বলার জন্য কেবল এক ধরণের অভদ্রতা এবং সেই কারণেই আপনি আপনাকে নিম্নগঠিত করে তোলেন।
এবিপারসন

4
আমি 6 বছর আগে অসভ্য বা ঘৃণ্য ছিল না। টোন স্পষ্টভাবে টোন মাধ্যমে আসে না। এটি সত্যিই বেশ হালকা হৃদয় বোঝানো ছিল ... আমিও সত্যিই মনে করি যে এই সমস্ত বছরগুলিতে আমার কাছে একটি কোডের নমুনার সাথে একটি লিঙ্ক ছিল এবং আমি এটি জানি না যে এটি কোথায় গেছে (ধরে নিচ্ছি যে আমি মনে রাখার মতোই সেখানে ছিলাম) )। : \
ক্রিসএইচ

আমি জানি না মেথডইনফো কীভাবে কাজ করে তবে এটি মূল্যবান বলে মনে হয়। আমি বলব আপনার উত্তরটি বর্তমানের গৃহীত উত্তরগুলির চেয়ে ভাল হওয়ার সম্ভাবনা রয়েছে তবে এটি সম্পূর্ণ করা দরকার। আপনি যদি কখনও এটির কাছাকাছি যান তবে এটি প্রশংসা হবে। যদি তা হয় তবে দয়া করে কোনও কোড নমুনায় লিঙ্ক করবেন না। ভবিষ্যতে এগুলি ভেঙে যেতে পারে। সম্ভবত উত্সের লিঙ্ক বা অব্যাহত পড়ার জন্য অতিরিক্ত তথ্যের সাথে নিজেকে নমুনা সরবরাহ করা ভাল।
স্প্যাগেটিকুক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.