I have several classes that exhibit a inheritance structure:
public class BaseClass
{
Guid ID {get;set;}
}
public class LeafType : BaseClass{ /* omitted */}
public class OtherLeafType : BaseClass{ /* omitted */}
public class Node : BaseClass
{
public List<LeafType> FirstLeaves {get;set;}
public List<OtherLeafType > SecondLeaves {get;set;}
public ???? AllLeaves {get;} //Returns all items in both FirstLeaves and SecondLeaves
}
In the example above, Node has two collections, whose elements derive from BaseClass. Does .Net have a collection that can combine these two collections and automatically update when either FirstLeaves or SecondLeaves changes? I have found the class System.Windows.Data.CompositeCollection, but it is in PresentationFramework, which to me indicates that it is intended for UI purposes. My class Node lives in an assembly that has nothing to do with the UI, so CompositeCollection looks like a bad fit. Is there any other class that would serve a similar purpose?
Update 1: Looking at the answers so far, it seems that my question was not clearly formulated: CompositeCollection Enables multiple collections and items to be displayed as a single list, but I was wondering if the .Net framework supplies a type with similar functionality that is not related to the GUI. If not, then I will roll my own solution, which looks very much like the answer by #Erik Madsen
I recommend using an iterator. It's not a collection but can converted to a collection via Linq's ToList() extension method.
The iterator provides a live view of the collection contents. You'll need to test what happens if the underlying collections are mutated while you're iterating through the IEnumerable. But generally this is considered bad practice.
public IEnumerable<BaseClass> AllLeaves
{
get
{
foreach (LeafType firstLeaf in FirstLeaves)
{
yield return firstLeaf;
}
foreach (OtherLeafType secondLeaf in SecondLeaves)
{
yield return secondLeaf;
}
}
}
public List<BaseClass> AllLeavesList()
{
return AllLeaves.ToList();
}
I believe concating one list to another may not work in your case as they are declared as different classes (even though they inherit the Base class). I would return a newly combined list.
public List<BaseClass> AllLeaves
{
get
{
List<BaseClass> l = new List<BaseClass>();
l.AddRange(FirstLeaves);
l.AddRange(SecondLeaves);
return l;
}
}
Related
Say that I have a public class MyClass: List<MyObjects>.
I want this class to have an inner method that manipulates the list, say
void ConstructListFromJSON(){
HoweverIshouldrefertomylist = JsonUtility.FromJson<List<MyObjects>("myObjects.json");
}
What should I put in place of the HoweverIshouldrefertomylist ? I've tried this, self and similar but it doesn't work. Surely there's a way to refer to the data strucure in the list?
You cannot reassign this, so clear the list and add whatever you want to add:
var objectsToStore = JsonUtility.FromJson<List<MyObjects>>("myObjects.json");
this.Clear();
this.AddRange(objectsToStore);
But in general, you really don't want to inherit from List<T>. See Why not inherit from List<T>?. Use composition instead:
public class MyClass
{
public List<YourObjects> YourObjects { get; set; }
public void ConstructListFromJSON()
{
YourObjects = JsonUtility.FromJson<List<MyObjects>("myObjects.json");
}
}
To properly generate classes representing your JSON, see Deserializing JSON into an object
To access a base object, just use the base keyword. But, for what you are showing, a different approach makes more sense - - just maintain a private object reference.
public class foo{
private List<MyObject> myList = null;
public foo(List<MyObject> l){
myList = l;
}
}
Now, the class has the list upon construction, but the list is private to the user. This is a better form of design. It uses composition over inheritance and provides a more loosely coupled design.
I have a pair of classes. These are literally copy/paste from my project:
public static class PageResult
{
public static PageResult<T> Create<T>(int totalCount, IList<T> items)
{
return new PageResult<T>()
{
TotalCount = totalCount,
Items = items,
};
}
}
public class PageResult<T>
{
public int TotalCount { get; set; }
public IList<T> Items { get; set; }
}
The reason I did this is so that I could use PageResult.Create(5, listOf5Items) as opposed to any other lengthier syntax. I didn't put the Create method in the PageResult(T) class because I'm pretty sure that requires me to type PageResult<int>(5, listOf5Numbers) instead, and that's an extra five characters...
But having two classes for it seems pretty lame. Is there a way I can get the more compact syntax without having a throwaway class just to store it?
As you already noted, you'd have to specify type parameters to even access the Create function, because that specific PageResult<T> class won't even exist until the JIT creates it when a method starts calling it. See Tuples for an instance of the .NET Framework itself doing just this pattern for the basically the same reason.
Note that another option is to make the PageResult class non-static, and inherit PageResult<T> : PageResult which will allow you to store a collection of PageResult objects without a type parameter. This can also be useful if you use an abstract PageResult
No. You could potentially make a VS snippet (or some other plugin/tool that could generate source code) to have some of the boilerplate typed out for you, but at the end of the day that code will need to be there.
For example:
public interface IFoo
{
//...
ICollection<IFoo> Children { get; }
//...
}
public class Foo : IFoo
{
//...
public ICollection<Foo> Children { get; private set; }
//...
public ICollection<IFoo> IFoo.Children
{
get
{
return Children; // Obviously wrong datatype, how do I cast this?
}
}
//...
}
So how do I correctly implement IFoo.Children? I tried Children.Cast<IFoo> but this returns an IEnumerable<IFoo> instead.
You'll need to think this through. If this cast would work, code would be allowed to add a completely different class object to your collection, one that implements IFoo but is otherwise completely unrelated to Foo. Your collection will now no longer be a collection of Foo. That of course can't be permitted. IEnumerable<> is fine, that can't alter the collection. ICollection<> is not.
The only possible way to get what you want is to create a copy of the collection. Like a List<IFoo>. You'll of course pay the perf for that. And can't easily see changes to that list, that's fixable. But you'll still have the fundamental problem that client code modifying that list still allows adding or removing objects that you don't know how to deal with.
Try Children.Cast<IFoo>().ToList().
Well, I've had to rewrite this as I've been down voted five times for giving too much detail... Go figure!
class BaseModel
{
public T[] Get<T>()
{
// return array of T's
}
public T Find<T>(object param)
{
// return T based on param
}
public T New<T>()
{
// return a new instance of T
}
}
class BaseRow
{
private BaseModel _model;
public BaseRow(SqlDataReader rdr, BaseModel model)
{
// populate properties of inheriting type using rdr column values
}
public void Save()
{
// calls _model.Save(this);
}
}
I currently have a number of classes that inherit the BaseModel class. Each of the methods exposed by BaseModel will return an instance, or an array of instances of a type that inherits the BaseRow class.
At the moment, when calling the exposed methods on the BaseModel via an inheriting class, i.e.
using(DeviceModel model = new DeviceModel())
{
DeviceRow row = model.Find<DeviceRow>(1);
DeviceRow[] rows = model.Get<DeviceRow>();
DeviceRow newRow = model.New<DeviceRow>();
}
I have to specify the type (a class that inherits the BaseRow class), as the methods in BaseModel/BaseRow do not know/care what type they are, other than they inherit from BaseRow.
What I would like to do is find a way to remove the need to specify the without having to replicate code in every class that inherits BaseModel, i.e.
class DeviceModel : BaseModel
{
public DeviceRow Find(object param)
{
return this.Find<DeviceRow>(param);
}
}
Note: Unfortunately I am unable to implement or use any third party solutions. That said, I have tried using Castle Active Record/nHibernate and to be honest, they are very big and heavy for what should be a very simple system.
Hopefully I haven't provided "too much" detail. If I have, please let me know.
Thanks
If I were you, I'd suggest making BaseModel a generic class. In a situation of "can't win either way", the code you've removed to make others happy might have told me more about what you're doing (not a criticism by any stretch - I appreciate your position).
class BaseModel<T>
{
public virtual T[] Get()
{
// return array of T's
}
public virtual T Find(object param)
{
// return T based on param
}
public virtual T New()
{
// return a new instance of T
}
}
That's your base, and then you have inheritors like:
class DeviceModel : BaseModel<Device>
{
public override Device New()
{
return new Device();
}
}
Now, any generic operations you define in DeviceModel will default to returning or using strongly typed Device. Notice the virtual methods in the BaseModel class. In the base class methods, you might provide some basic operations predicated upon using T's or something. In sub-classes, you can define more specific, strongly typed behavior.
I'd also comment that you might want to pull back a little and consider the relationship of BaseModel and BaseRow. It appears that you're defining a parallel inheritance hierarchy, which can tend to be a code smell (this is where more of your code might have come in handy -- I could be wrong about how you're using this). If your ongoing development prospects are that you're going to need to add a FooRow every time you add a FooModel, that's often a bad sign.
Suppose I have Class A with some properties and Attributes, and Class B with the same, how can I merge these 2 class Properties and properties Attributes into 1 class at runtime, or better is how can I add these 2 classes into a a third class as properties of this new class with their Fields, Properties, Methods, etc... at Runtime ?
Using reflection or the News .NET 4.0 Dynamic or expando Object
Edit: Damn I am sorry to all for not being clear, what I want is to create a dynamic ViewModel for MVC, where other classes are in some other assemblies, and I want them to be part of the model with their Datavalidation attributes. and I don't know how many or what exactly these classes are gonna be, so I want to iterate through assemblies and choose them then add them to the main View Model.
You can't change a type at runtime. Expando might be an option, but I am not clear how you want to interact with this object, as you would seem to be limited to reflection, and expando is not a huge friend of reflection.
It might help to clarify your requirement here, but IMO you might do better to consider loading (at runtime) a property-bag based on reflection from the two inputs; something like a Dictionary<string,object> which would let you map named keys to values.
One other thing that might be what you are after here is partial classes, but this is a single type spread over multiple source files:
partial class Foo {
private string bar;
}
partial class Foo {
public string Bar { get {return bar;} set {bar = value;} }
}
A final option here is TypeBuilder, but that is massive overkill in most scenarios.
Assuming you don't have access to the code for either of the classes (otherwise you could just merge the code), you can create a wrapper that aggregates the two classes with the combined interfaces:
public class AandB
{
private ClassA _instanceA = new ClassA();
private ClassB _instanceB = new ClassB();
public bool PropertyA
{
get
{
return _instanceA.PropertyA;
}
set
{
_instanceA.PropertyA = value;
}
}
public bool PropertyB
{
get
{
return _instanceB.PropertyB;
}
set
{
_instanceB.PropertyB = value;
}
}
}