আমি কীভাবে একটি বাহ্যিক সমাবেশ থেকে একটি অভ্যন্তরীণ ক্লাস অ্যাক্সেস করতে পারি?


100

একটি সমাবেশ যা আমি সংশোধন করতে পারবেন না (ভেন্ডর-সরবরাহকৃত) যা ফিরে একটি পদ্ধতি আছে রয়ে বস্তুর টাইপ কিন্তু সত্যিই একটি অভ্যন্তরীণ ধরনের হয়।

আমি কীভাবে আমার সমাবেশ থেকে ক্ষেত্র এবং / অথবা অবজেক্টের পদ্ধতিগুলি অ্যাক্সেস করতে পারি?

মনে রাখবেন যে আমি বিক্রেতা-সরবরাহকারী সমাবেশটি সংশোধন করতে পারি না।

সংক্ষেপে, আমার যা আছে তা এখানে:

বিক্রেতার কাছ থেকে:

internal class InternalClass
  public string test;
end class

public class Vendor
  private InternalClass _internal;
  public object Tag {get{return _internal;}}
end class

আমার সমাবেশ থেকে বিক্রেতার সমাবেশটি ব্যবহার করে।

public class MyClass
{
  public void AccessTest()
  {
    Vendor vendor = new Vendor();
    object value = vendor.Tag;
    // Here I want to access InternalClass.test
  }
}

উত্তর:


85

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

আপনি এটিকে জনসাধারণের উদাহরণ হিসাবে বর্ণনা করেছেন; প্রতিবিম্ব মাধ্যমে এটি পেতে:

object obj = ...
string value = (string)obj.GetType().GetField("test").GetValue(obj);

যদি এটি আসলে সম্পত্তি (ক্ষেত্র নয়):

string value = (string)obj.GetType().GetProperty("test").GetValue(obj,null);

যদি এটি সর্বজনীন না হয় তবে আপনাকে / এর BindingFlagsওভারলোড ব্যবহার করতে হবে ।GetFieldGetProperty

গুরুত্বপূর্ণ একদিকে : প্রতিবিম্বের সাথে সতর্ক থাকুন; পরবর্তী সংস্করণে (আপনার কোড ভঙ্গ করা) বাস্তবায়ন পরিবর্তন হতে পারে, বা এটি অবরুদ্ধ হতে পারে (আপনার কোড ভঙ্গ করা), অথবা আপনার পর্যাপ্ত "বিশ্বাস" (আপনার কোড ভঙ্গ করা) নাও থাকতে পারে। আপনি প্যাটার্ন স্পট করছেন?


মার্ক আমি অবাক হই ... ব্যক্তিগত ক্ষেত্র / বৈশিষ্ট্যগুলি অ্যাক্সেস করা সম্ভব তবে সঠিক ধরণের সাহায্যে গেটভ্যালু দ্বারা প্রত্যাবর্তিত বস্তুটি ফেলে দেওয়ার কোনও উপায় আছে কি?
কোডিংএডভেঞ্চারস

4
@ জিওভান্নি ক্যাম্পো যদি আপনি স্ট্যাটিকালি জানেন তবে প্রকারটি কী: নিশ্চিত - সবেমাত্র কাস্ট করুন। আপনি টাইপ স্ট্যাটিক্যালি জানা না থাকলে - এটা স্পষ্ট নয় কি হবে এমনকি এই গড়
মার্ক Gravell

যে সমস্ত লোকেরা সত্যিকারের পাবলিক এপিআই-র অন্তর্গত হিসাবে ইন্টার্নাল হিসাবে জিনিস প্রকাশ করে তাদের সম্পর্কে কী বলা যায়? বা তারা ব্যবহার করেছে InternalsVisibleToকিন্তু আপনার সমাবেশটি অন্তর্ভুক্ত করেনি? প্রতীকটি যদি সত্যই লুকানো না থাকে তবে এটি এবিআইয়ের অংশ।
বিনকি

211

আমি কেবল একটি ক্ষেত্রে দেখছি যে আপনি নিজের অভ্যন্তরীণ সদস্যদের অন্য সমাবেশে প্রকাশের অনুমতি দেবেন এবং সেটি হচ্ছে পরীক্ষার উদ্দেশ্যে।

এই বলে যে "বন্ধু" অ্যাসেম্বলিগুলিকে অভ্যন্তরীণ প্রবেশের অনুমতি দেওয়ার একটি উপায় আছে:

প্রকল্পের अस্যামিলিআইএনফো ফাইলগুলিতে আপনি প্রতিটি সমাবেশের জন্য একটি লাইন যুক্ত করেন।

[assembly: InternalsVisibleTo("name of assembly here")]

এই তথ্য এখানে পাওয়া যায়।

আশাকরি এটা সাহায্য করবে.


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

4
আমি মনে করি না যে এই উত্তরটি সাহায্য করে - ওপি বলে যে তিনি বিক্রেতার সমাবেশকে সংশোধন করতে পারবেন না, এবং এই উত্তরটি বিক্রেতার প্রকল্পের এসেম্বলিআইএনএফ.সি.এস ফাইলটি সংশোধন করার বিষয়ে কথা বলে
সাইমন গ্রিন

6

আমি একটি বিষয় নিয়ে তর্ক করতে চাই - আপনি মূল সমাবেশটি বাড়িয়ে তুলতে পারবেন না - মনো-সিসিল ব্যবহার করে আপনি [InternalsVisibleTo(...)]3pty সমাবেশে ইনজেক্ট করতে পারেন । এখানে আইনী বিভ্রান্তি থাকতে পারে মনে করুন - আপনি 3pty সমাবেশ এবং প্রযুক্তিগত জালিয়াতির সাথে জগাখিচুড়ি করছেন - যদি সমাবেশটির শক্ত নাম হয় তবে হয় আপনাকে এটি ছিনিয়ে নিতে হবে বা আলাদা কী দ্বারা পুনরায় সই করতে হবে।

 Install-Package Mono.Cecil

এবং কোডটি এর মতো:

static readonly string[] s_toInject = {
  // alternatively "MyAssembly, PublicKey=0024000004800000... etc."
  "MyAssembly"
};

static void Main(string[] args) {
  const string THIRD_PARTY_ASSEMBLY_PATH = @"c:\folder\ThirdPartyAssembly.dll";

   var parameters = new ReaderParameters();
   var asm = ModuleDefinition.ReadModule(INPUT_PATH, parameters);
   foreach (var toInject in s_toInject) {
     var ca = new CustomAttribute(
       asm.Import(typeof(InternalsVisibleToAttribute).GetConstructor(new[] {
                      typeof(string)})));
     ca.ConstructorArguments.Add(new CustomAttributeArgument(asm.TypeSystem.String, toInject));
     asm.Assembly.CustomAttributes.Add(ca);
   }
   asm.Write(@"c:\folder-modified\ThirdPartyAssembly.dll");
   // note if the assembly is strongly-signed you need to resign it like
   // asm.Write(@"c:\folder-modified\ThirdPartyAssembly.dll", new WriterParameters {
   //   StrongNameKeyPair = new StrongNameKeyPair(File.ReadAllBytes(@"c:\MyKey.snk"))
   // });
}

4
আমার জন্য, সংশোধন করা যাবে না এর অর্থ এটি একটি নুগেট থেকে এসেছে এবং আমি পরিবর্তনগুলি সহ একটি স্থানীয় সংকেত তৈরি এবং পরিচালনা করতে চাই না। এছাড়াও, কিছু লোকের জন্য, একটি শক্তিশালী নাম হ'ল ব্যাপার হবে। তবে এটি একটি আকর্ষণীয় বিষয়।
বিনকি

3

প্রতিবিম্ব।

using System.Reflection;

Vendor vendor = new Vendor();
object tag = vendor.Tag;

Type tagt = tag.GetType();
FieldInfo field = tagt.GetField("test");

string value = field.GetValue(tag);

শক্তিটি বুদ্ধিমানের সাথে ব্যবহার করুন। ত্রুটি পরীক্ষা করা ভুলবেন না। :)


-2

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


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