问题
Say I have a bunch of classes that implement an interface:
public interface IBuilding
{
string WhatAmI();
}
Class house:IBuilding
{
string Ibuilding.WhatAmI(){return "A House";}
}
Class Skyscraper:IBuilding
{
string Ibuilding.WhatAmI(){return "A Skyscraper";}
}
Class Mall:IBuilding
{
string Ibuilding.WhatAmI(){return "A Mall";}
}
And then I want to dynamically choose what to instantiate the class:
enum buildingType { house, Skyscraper, Mall };
string someMethodOrAnother()
{
string building= textboxBuildingType.Text;
Ibuilding MyBuildingClass;
buildingType UserSelectedClass = (buildingType) Enum.Parse(typeof(buildingType), building);
if (Enum.IsDefined(typeof(buildingType), UserSelectedClass) )
{
MyBuildingClass = (some code that dynamically creates a class instance);
}
else
{
MyBuildingClass = new house();
}
return MyBuildingClass.WhatAmI;
}
Now I could do this in a switch statement, but I thought I had found a more elegant technique. Or is the whole idea of using an interface wrong? Perhaps I need a delegate instead?
回答1:
In general, I would use a Dictionary with Activator.CreateInstance:
Dictionary<buildingType, Type> typeMap = new Dictionary<buildingType, Type>()
{
{ buildingType.House, typeof(House) }
}
IBuilding building = (IBuilding)Activator.CreateInstance(typeMap[userSelection]);
If this were WPF, you could use a converter to do this directly from the view to the view model.
回答2:
If I understand what you're trying to do correctly, there are several ways to go about this but at the end of the day you'll have to have some logic that picks one particular type from a list of available types.
Some options (not an exhaustive list):
Use reflection to inspect your assemblies and determine what types implement the interface you want.
Use dependency injection (like LightInject) to do the assembly inspection for you and give you a list of types you can instantiate. DI libraries have various features to control how to discover types. This is a very flexible solution and the work is done for you.
Use an XML file (or other file format) to describe types that can be used. This is not very flexible but it allows you to list the types you want to be available regardless of what's in the assemblies. (Obviously, you can't make a non-existent type available but you can hide existing types without recompiling the code.)
At the end, you'll end up with a list of types that implement the interface you need. With the list you have to implement some kind of logic to actually pick one particular type that you'll instantiate - this logic is specific to your application (maybe pick the type based on a list in a listbox, etc.): no one can tell you how to do this.
Once you pick the type, you can just use Activator.CreateInstance() to create an instance of the type you picked. Alternatively, if you use LightInject, you can ask the library to return an instance of the specific type for you.
来源:https://stackoverflow.com/questions/26809862/can-i-dynamically-instantiate-an-interface-at-runtime-well-yes-i-can-but-is-the