polymorphism, generics and anonymous types C#
Consider the following scenario.
Document -> Section -> Body -> Items
Document has sections, a section contains a body. A body has some text and a list of items. The items is what the question is about. Sometimes the items is a basic list of string, but sometimes the items contain a list of a custom datatype.
So:
public class Document
{
public Section[] Sections{get;set;}
}
public class Section
{
public SectionType Type{get;set;}
public Body {get;set;}
}
public class Body
{
//I want the items to be depending on the section type.
//If e.g. the sectiontype is experience, I want the Items to be created with type //Experience. If sectiontype is default I want the Items to be created with type string
public Items<T> Items {get;set;}
}
public class Items<T>:IEnumerable, IEnumerator
{
// Do all the plumbing for creating an enumerable collection
}
public class Experience
{
public string Prop1{get;set;}
public string Prop2 {get;set;}
}
I can´t get this to work. The property Items has to be defined by a type in order to compile. I am stuck here. I can fix this easily by creating a Section class for each of the kind of sections I use. But the thing is that all the other code is the same and all the operations on the section will be the same. The only thing different is the type of list used in the Body.
What is the best开发者_StackOverflow中文版 practice for this. I have tried generics, abstraction etc. I can make it work if creating the Items class directly from the calling program, but I can´t get it to work if Items is declared a property on another class.
I can provide more details if needed. Thank you guys and girls for your support.
This class isn't valid:
public class Body
{
public Items<T> Items {get;set;}
}
You need to define a concrete type here OR make Body
a generic type also. So either:
public class Body<T>
{
public Items<T> Items {get;set;}
}
or:
public class Body
{
public Items<MyClass> Items {get;set;}
}
Make an interface for Items
public interface IItems: IEnumerable, IEnumerator{
}
public class Items<T>: IItems
{
// Do all the plumbing for creating an enumerable collection
}
Then use that everywhere else.
public class Body
{
//I want the items to be depending on the section type.
//If e.g. the sectiontype is experience, I want the Items to be created with type //Experience. If sectiontype is default I want the Items to be created with type string
public IItems Items {get;set;}
}
The most obvious option is declare your list of type object, but then you have to deal with the performance hit of boxing and unboxing of the object. I think I would create an interface that defines the behavior you are looking for from the item and make sure each item implements that interface.
public IMyInterface
{
string dosomething();
}
public Items<IMyInterface> Items {get;set;}
Then you could ask each item to do something useful as you are iterating through them.
This could work for you:
public class Document<T> where T: IEnumerable, IEnumerator
{
private Section<T>[] Sections{get;set;}
}
private class Section<T>
{
private Body<T> body {get;set;}
}
private class Body<T>
{
private Items<T> Items {get;set;}
}
private class Items<T>:IEnumerable, IEnumerator
{
// Do all the plumbing for creating an enumerable collection
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
/* Needed since Implementing IEnumerator*/
public bool MoveNext()
{
return false;
}
public void Reset()
{
}
public object Current
{
get{ return new object();}
}
}
精彩评论