2013-07-12 2 views
2

Представьте, что у меня есть визуальное студийное решение, содержащее два проекта. В этом случае проект 1 осознает Проект 2, но проект 2 не знает о проекте 1.Справочный интерфейс со стороны проекта

Проект 1

using Project2; 

namespace Project1 
{ 
    public class ClassA : IMyInterface {} 

    public class Main { 

     public void MainMethod() 
     { 
      ARandomClass aRandomClass = new ARandomClass(); 
      IMyInterface classA = new ClassA(); 
      aRandomClass.MyItem = classA; 
      aRandomClass.MyMethod(); 
     } 

    } 
} 

Project 2

namespace Project2 
{ 
    public interface IMyInterface { } 

    public class ARandomClass { 
     public IMyInterface MyItem { get; set; } 

     public void MyMethod() { 
     Type type = MyItem.GetType(); // what happens here? 
     } 
    } 
} 

Мой вопрос действительно, что произойдет, если мы попытаемся получить тип объекта внутри проекта, не имеющего ссылки/знания этого типа?

Будет ли он возвращать интерфейс? Может это? Это как-то способно ссылаться на тип? Будет ли он возвращать «объект»? Или он вообще что-то сделает?

ответ

3

Он вернет фактический тип ClassA.

Вся информация о типе доступна и проверяется с помощью отражения. Вы просто не можете напрямую ссылаться на тип во время компиляции.

Проект 2 может до сих пор называют членами по ClassA, было бы просто трудно/громоздким, потому что вы будете ограничены использованием отражения или dynamic.

public void MyMethod() { 
    Type type = MyItem.GetType(); //gets a `System.Type` representing `ClassA' 
    Console.WriteLine(type.FullName);//outputs "Project1.ClassA" 
} 

Просто продемонстрировать, что вы можете или не может сделать, скажем, ClassA был определен как:

public class ClassA : IMyInterface 
{ 
    public string MyField = "Hello world!"; 
} 

Вы не смогли бы сделать это:

public void MyMethod() { 
    Console.WriteLine(MyItem.MyField); //compiler error 
} 

Вы могли сделайте это, потому что Project2 может получить доступ к информации из Project1 во время выполнения:

public void MyMethod() { 
    //lookup the field via reflection 
    Type type = MyItem.GetType(); 
    Console.WriteLine(type.GetField("MyField").GetValue(MyItem)); 

    //simpler way than above using dynamic, but still at runtime 
    dynamic dynamicItem = MyItem; 
    Console.WriteLine(MyItem.MyField); 
} 

Но вы не могли бы сделать это, потому что Проект2 не имеет никакого знания Проект1 во время компиляции:

public void MyMethod() { 
    //cast to type ClassA 
    ClassA classAMyItem = (ClassA)MyItem; //compile error 
    Console.WriteLine(classAMyItem.MyField); //compile error 
} 

В основном это один из жильцов полиморфизма, хотя. Ваш MyMethod не должен знать, и не должен заботиться , что класс MyItem находится за пределами него IMyInterface. Обычно он должен заботиться только о доступе к свойствам, методам и событиям, как определено на IMyInterface. Если это делает заботясь о том, чтобы он являлся экземпляром ClassA, тогда вам, возможно, захочется пересмотреть свой дизайн или использование.

+0

Спасибо, что все имеет смысл. Мне всегда казалось, что методы в одном проекте выполняются внутри этого проекта и что они имеют доступ только к типам, доступным во время компиляции. Сценарий, который я описал, произошел со мной случайным образом и продолжал прослушивать меня достаточно, чтобы опубликовать этот вопрос! – kaykayman

1

Код, который вы видите в проекте 2, по-прежнему будет запущен из проекта 1, вот где ваш звонок и, следовательно, сможет предоставить вам правильную информацию о типе интерфейса.

Мое предположение было бы выходом будет что-то вроде Project1.ClassA с тем, что у вас есть до него. Но чтобы быть уверенным, просто запустите этот код и посмотреть, что вывод, который вы получите

2

вы получите тип, как Project1.ClassA

0
public void MyMethod() { 
     Type type = MyItem.GetType(); // what happens here? 
     } 

переменную типа будет указывать на ваш AClass. Вы можете изменить свой код выглядит следующим образом:

public IMyInterface MyMethod() 
     { 
      Type type = MyItem.GetType(); // what happens here? 
      IMyInterface value = (IMyInterface)Activator.CreateInstance(type); 
      return value; 
     } 

Теперь вы можете использовать экземпляр вашего класса с помощью интерфейса без особого отражения (Активатор с помощью отражения внутри, чтобы создать экземпляр).

Смежные вопросы