Câu hỏi C # - Cách truy cập lớp bên trong từ lắp ráp ngoài


Có một hội đồng mà tôi không thể sửa đổi (được cung cấp bởi nhà cung cấp) có phương thức trả về một vật loại nhưng thực sự là loại nội bộ.

Làm thế nào tôi có thể truy cập vào các lĩnh vực và / hoặc phương pháp của đối tượng từ lắp ráp của tôi?

Hãy nhớ rằng tôi không thể sửa đổi lắp ráp do nhà cung cấp cung cấp.

Về bản chất, đây là những gì tôi có:

Từ nhà cung cấp:

internal class InternalClass
  public string test;
end class

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

Từ lắp ráp của tôi bằng cách sử dụng lắp ráp nhà cung cấp.

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

75
2018-05-28 13:27


gốc




Các câu trả lời:


Nếu không có quyền truy cập vào loại (và không có "InternalsVisibleTo" vv), bạn sẽ phải sử dụng sự phản ánh. Nhưng một câu hỏi hay hơn sẽ là: Nên bạn đang truy cập dữ liệu này? Nó không phải là một phần của hợp đồng loại công cộng ... nó nghe có vẻ như tôi được coi là đối tượng mờ đục (vì mục đích của họ, không phải của bạn).

Bạn đã mô tả nó như một trường hợp công khai; để có được điều này thông qua sự phản ánh:

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

Nếu nó thực sự là một tài sản (không phải là một lĩnh vực):

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

Nếu không công khai, bạn cần sử dụng BindingFlags quá tải của GetField/GetProperty.

Quan trọng sang một bên: hãy cẩn thận với sự phản chiếu như thế này; việc triển khai có thể thay đổi trong phiên bản tiếp theo (vi phạm mã của bạn), hoặc nó có thể bị làm xáo trộn (vi phạm mã của bạn), hoặc bạn có thể không có đủ "tin cậy" (vi phạm mã của bạn). Bạn có phát hiện ra mẫu không?


74
2018-05-28 13:32



Wooo .. 2 phút! Đó là gần! Cũng nói Marc (như mọi khi). : D - Galilyou
Tuyệt quá! Điều đó hoạt động. Tôi nghĩ rằng tôi không thể truy cập internals theo cách này ... Cảm ơn bạn rất nhiều - Stécy
Marc Tôi tự hỏi ... có thể truy cập các trường / thuộc tính riêng tư nhưng có cách nào để truyền đối tượng được trả về bởi GetValue bằng đúng loại không? - codingadventures
@GiovanniCampo nếu bạn biết tĩnh loại gì là: chắc chắn - chỉ cần cast. Nếu bạn không biết loại tĩnh - không rõ điều này sẽ làm gì nghĩa là - Marc Gravell♦
Điều gì về những người xuất bản những thứ dưới dạng nội bộ thực sự là một phần của API công khai? Hoặc họ đã sử dụng InternalsVisibleTonhưng không bao gồm lắp ráp của bạn? Nếu biểu tượng không thực sự ẩn, đó là một phần của ABI. - binki


Tôi chỉ thấy một trường hợp mà bạn sẽ cho phép tiếp xúc với các thành viên nội bộ của bạn đến một hội đồng khác và đó là cho mục đích thử nghiệm.

Nói rằng có một cách để cho phép hội đồng "Friend" truy cập vào internals:

Trong tệp AssemblyInfo.cs của dự án bạn thêm một dòng cho mỗi assembly.

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

thông tin này có sẵn đây.

Hi vọng điêu nay co ich.


182
2018-06-12 00:52



Mới hôm nay tôi đã lúng túng một màn hình và nghe nói về việc phơi bày các thành viên nội bộ của một hội đồng nhất định để một hội đồng khác (hội đồng kiểm tra) có quyền truy cập vào nó, nhưng không biết làm thế nào để làm điều đó. Cảm ơn bạn! - Ricardo Amores
Bình chọn vì đây là thông tin hữu ích cho tôi ... mặc dù đây không phải là câu trả lời cho câu hỏi :-D - yeyeyerman
câu hỏi cụ thể nói rằng hội đồng đối tác không thể sửa đổi được. Phiếu phản đối. - danielpops
Tôi đến đây để tìm cách vạch trần một lớp học để kiểm tra. Câu hỏi này trả lời câu hỏi của tôi! Bỏ phiếu lên. - TheSilverBullet
nó là một tài liệu tham khảo tốt về cách phơi bày internals đến một hội đồng người bạn, nhưng các câu hỏi mô tả một tình huống mà một hội đồng được cung cấp không thể được sửa đổi, do đó, bình chọn xuống. - eitanpo


Phản ánh.

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);

Sử dụng sức mạnh một cách khôn ngoan. Đừng quên kiểm tra lỗi. :)


3
2018-05-28 13:34





Tôi muốn tranh luận một điểm - rằng bạn không thể tăng cường lắp ráp ban đầu - sử dụng Mono.Cecil bạn có thể tiêm [InternalsVisibleTo(...)] để lắp ráp 3pty. Lưu ý có thể có ý nghĩa pháp lý - bạn đang rối tung với lắp ráp 3pty và các tác động kỹ thuật - nếu lắp ráp có tên mạnh, bạn cần phải tháo nó hoặc ký lại bằng phím khác.

 Install-Package Mono.Cecil

Và mã như:

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"))
   // });
}

3
2018-06-02 13:03



Đối với tôi, không thể sửa đổi có nghĩa là nó đến từ một cái nuget và tôi không muốn phải tạo và quản lý một cái nuget cục bộ với những sửa đổi. Ngoài ra, đối với một số người, việc mất một tên mạnh sẽ là vấn đề. Nhưng đây là một điểm thú vị. - binki


Vâng, bạn không thể. Các lớp bên trong không thể nhìn thấy được bên ngoài assembly của chúng, do đó không có cách nào rõ ràng để truy cập trực tiếp vào lớp -AFAIK. Cách duy nhất là sử dụng thời gian chạy trễ ràng buộc thông qua sự phản chiếu, sau đó bạn có thể gọi các phương thức và thuộc tính từ lớp bên trong gián tiếp.


-3
2018-05-28 13:34



giải pháp của zonkflut đã làm việc cho tôi trong quá khứ - phlip
mặc dù nó dựa vào việc sửa đổi hội đồng được gọi là - phlip
Bạn có thể gọi bất cứ điều gì với sự phản ánh - MrHinsh - Martin Hinshelwood