Làm thế nào để truyền Object sang kiểu thực của nó?


120

Nếu tôi có:

void MyMethod(Object obj) {   ...   }

Làm cách nào để tôi có thể truyền objđến loại thực tế của nó?


2
Loại được biết tại thời điểm biên dịch?
psubsee2003

1
Và bạn mong đợi đạt được điều gì từ điều này? Vui lòng cho chúng tôi biết bạn đang cố gắng đạt được điều gì hơn là cách bạn mong đợi để đạt được nó.
Jon Skeet

@JonSkeet: Tôi muốn có thể gọi một hàm từ đối tượng. Hiện tại obj.MyFunction();không biên dịch, mặc dù tôi biết rằng đối tượng thực có chức năng đó.
Paul Lassiter

@ psubsee2003: không, không phải vậy, bởi vì nó là một tham chiếu đối tượng được truyền qua interop.
Paul Lassiter

3
@PaulLassiter: Nếu bạn không biết kiểu, cái gì khai báo MyFunctionphương thức?
Jon Skeet

Câu trả lời:


194

Nếu bạn biết loại thực tế, thì chỉ cần:

SomeType typed = (SomeType)obj;
typed.MyFunction();

Nếu bạn không biết loại thực tế, thì: không hẳn, không. Thay vào đó, bạn sẽ phải sử dụng một trong số:

  • sự phản chiếu
  • triển khai một giao diện nổi tiếng
  • năng động

Ví dụ:

// reflection
obj.GetType().GetMethod("MyFunction").Invoke(obj, null);

// interface
IFoo foo = (IFoo)obj; // where SomeType : IFoo and IFoo declares MyFunction
foo.MyFunction();

// dynamic
dynamic d = obj;
d.MyFunction();

1
Cú pháp tương đương trong Swift là gì?
Nagendra Rao

1
Nevermind, được tìm thấy asđể đánh máy và type(of: ClassName)chức năng để kiểm tra kiểu phiên bản.
Nagendra Rao

42

Tôi không nghĩ rằng bạn có thể (không phải không có phản ánh), bạn cũng nên cung cấp một loại cho chức năng của mình:

void MyMethod(Object obj, Type t)
{
    var convertedObject = Convert.ChangeType(obj, t);
    ...
}

CẬP NHẬT :

Điều này có thể làm việc cho bạn:

void MyMethod(Object obj)
{
    if (obj is A)
    {
        A a = obj as A;
        ...
    } 
    else if (obj is B)
    {
        B b = obj as B;
        ...
    }
}

4
Đây thực sự là một câu trả lời vô ích, không quan trọng đến số phiếu bầu. Phản ánh của một đối tượng kiểu đối tượng sẽ không mang lại "kiểu thực tế" của đối tượng, như OP yêu cầu. Ngoài ra, logic MyMethod của bạn còn thiếu sót vì obj có thể thuộc loại A và nó cũng có thể thuộc loại B. Logic của bạn không cung cấp "loại thực tế" (như OP yêu cầu) - nó cung cấp một loại tương thích và không nhất thiết loại mong muốn tại đó.
Jazimov

sử dụng obj.GetType (). Điều đó chắc chắn sẽ trả về loại thực tế của nó.
JSON

3

Làm thế nào về JsonConvert.DeserializeObject (object.ToString ());


Đây không phải là một câu trả lời thỏa mãn. Câu hỏi của OP không liên quan gì đến Json hoặc tuần tự hóa.

@ user12637955 đây thực sự là một câu trả lời hoạt động, nhưng có độ phức tạp lớn hơn, do quyền anh và unboxing, tức là đối tượng -> ToString () -> thành kiểu cụ thể. Để chính xác hơn, nó sẽ trông như thế này:var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
Coke

1

Trong trường hợp của tôi, AutoMapper hoạt động tốt.

AutoMapper có thể ánh xạ đến / từ các đối tượng động mà không cần bất kỳ cấu hình rõ ràng nào:

public class Foo {
    public int Bar { get; set; }
    public int Baz { get; set; }
}
dynamic foo = new MyDynamicObject();
foo.Bar = 5;
foo.Baz = 6;

Mapper.Initialize(cfg => {});

var result = Mapper.Map<Foo>(foo);
result.Bar.ShouldEqual(5);
result.Baz.ShouldEqual(6);

dynamic foo2 = Mapper.Map<MyDynamicObject>(result);
foo2.Bar.ShouldEqual(5);
foo2.Baz.ShouldEqual(6);

Tương tự, bạn có thể ánh xạ thẳng từ từ điển sang các đối tượng, AutoMapper sẽ sắp xếp các phím với tên thuộc tính.

thêm thông tin https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping


1

Phương pháp này có thể không hiệu quả nhất nhưng đơn giản và hiệu quả.

Nó thực hiện hai hoạt động: đầu tiên nó gọi .ToString () về cơ bản là tuần tự hóa, và sau đó là giải mã hóa bằng Newtonsoft nuget (mà bạn phải cài đặt).

public T Format<T>(Object obj) =>
    JsonConvert.DeserializeObject<T>(obj.ToString());

Bạn nên mô tả ngắn gọn câu trả lời của mình cho những người đọc trong tương lai.
Suraj Kumar

0

Nếu MyFunction()phương thức của bạn chỉ được xác định trong một lớp (và các lớp con của nó), hãy thử

void MyMethod(Object obj) 
{
    var o = obj as MyClass;
    if (o != null)
        o.MyFunction();
}

Nếu bạn có một số lượng lớn các lớp không liên quan xác định hàm bạn muốn gọi, bạn nên xác định một giao diện và làm cho các lớp của bạn xác định giao diện đó:

interface IMyInterface
{
    void MyFunction();
}

void MyMethod(Object obj) 
{
    var o = obj as IMyInterface;
    if (o != null)
        o.MyFunction();
}

0

Truyền nó sang kiểu thực của nó nếu bây giờ bạn là kiểu, chẳng hạn như kiểu nó được định hướng từ lớp có tên abc. Bạn có thể gọi hàm của mình theo cách này:

(abc)(obj)).MyFunction();

nếu bạn không biết chức năng, nó có thể được thực hiện theo một cách khác. Không dễ dàng luôn luôn. Nhưng bạn có thể tìm thấy nó theo một cách nào đó bằng chữ ký của nó. Nếu đây là trường hợp của bạn, bạn nên cho chúng tôi biết.


-1

Truyền sang loại thực tế rất dễ dàng:

void MyMethod(Object obj) {
    ActualType actualyType = (ActualType)obj;
}

8
Điều này là phi logic. Bạn thực sự không biết loại thực tế. Làm thế nào bạn phải làm điều đó?
Allen Linatoc

-2
Implement an interface to call your function in your method
interface IMyInterface
{
 void MyinterfaceMethod();
}

IMyInterface MyObj = obj as IMyInterface;
if ( MyObj != null)
{
MyMethod(IMyInterface MyObj );
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.