How can i make the following class as general as possible (for maximum reuse) without creating too many classes of the same type, albeit with one extra property.
I want to avoid writing 3 slightly different versions of the same class
1# Class with No SubContent
public class Content
{
public string PageName { get; set; }
}
2# Class with Subcontent
public class Content
{
public string PageName { get; set; }
public IList<Content> SubContent {get; set;} //same as class
}
3# Class with sub content of another type
public class Content
{
public string PageName { get; set; }
public IList<DetailContent> SubContent {get; set;} //Note the different def
}
Of course i can create a generic class, but i find this confusing for consumers. It is inferring that the class is of Type T, when in fact its the Property that requires the type
public class Content<T>
{
public string PageName { get; set; }
public IList<T> SubContent {get; set;} //Note the different def
}
Generic Properties are not supported. So are there any patterns or suggestion on how i can handle this problem?
Perhaps you can have a look at the Composite Design Pattern
whats wrong with:
public class Content<T>
{
public string PageName { get; set; }
public IList<T> SubContent { get; set; } //Note the different def
}
?
it works you know...
What about
public class Content
{
public string PageName { get; set; }
}
public class ContentWithSubContent<T> : Content
{
public IList<T> SubContent { get; set; }
}
and if you want to be able to access SubContent not knowing the actual type, you could use
public class Content
{
public string PageName { get; set; }
}
public interface IContentWithSubContent
{
IEnumerable SubContent { get; }
}
public class ContentWithSubContent<T> : Content, IContentWithSubContent
{
public IList<T> SubContent { get; set; }
IEnumerable IContentWithSubContent SubContent
{
get { return this.SubContent; }
}
}
that way you can access the SubContent property bypassing generics if you need to, by using IContentsWithSubContent rather than Content.
Why not make an interface for the content classes:
public interface IContent {
public function GetContent()
}
and then you can use
List<IContent> in your content class?
you could even make the interface generic
Related
Is it possible to prevent a child class from having the same property name as a parent class?
For example:
public class Vehicle {
public string Title { get; set; }
public string Make { get; set; } // Honda, etc.
}
public class Car : Vehicle {
public string Title { get; set; }
public bool HasWarranty { get; set; }
}
I'd like the above to throw a build error saying that Vehicle already has a property named Title. Is this possible? If another developer on my team does a copy/paste from Car to make a Motorcycle class and decides to a Make property, while Vehicle already has Make as a property name, it feels like a DRY violation.
One simple way to enforce something like this is with Attributes. You can create the concept of having custom validations that run against your codebase on wakeup of your application.
Pseudo Code:
public abstract ValidationAttribute : Attibute
{
public abstract bool Validate(Type target);
}
------
public EnforceDistinctMembersAttribute : ValidationAttribute
{
string[] members;
public EnforceDistinctMembersAttribute(params string[] members)
{
this.members = members;
}
public override bool Validate(Type target)
{
if (target......
}
}
Create a method that will loop over all types, find all ValidationAttributes and call the Validate method of each one passing in the Type it was attached to. If you come across an issue, you can throw an exception or log or so on.
Remember this is only pseudo code and its only meant to get the idea across.
Usage:
[EnforceDistinctMembers] // or
[EnforceDistinctMembers(nameof(Title), nameof(Make))]
public class Vehicle {
public string Title { get; set; }
public string Make { get; set; } // Honda, etc.
}
public class Car : Vehicle {
public string Title { get; set; }
public bool HasWarranty { get; set; }
}
I have a model class that is extended from the realm object. In some cases, I use this model as both realm model and POST operations. Currently, the realm IList properties unable to support setter options. Is there any option or way to achieve this?
Here is my current code:
[JsonObject]
public class Product : RealmObject, IProduct
{
[MapTo("name")]
[JsonProperty("name")]
public string Name { get; set; }
[MapTo("skuDetails")]
[JsonProperty("skuDetails")]
public IList<SkuDetail> SkuDetails { get; }
}
My requirement :
[JsonObject]
public class Product : RealmObject, IProduct
{
[MapTo("name")]
[JsonProperty("name")]
public string Name { get; set; }
[MapTo("skuDetails")]
[JsonProperty("skuDetails")]
public IList<SkuDetail> SkuDetails { get; set; }
}
you need to derive your class according your need.
this is totally possible like the code below:
public interface ITest
{
IList<object> SkuDetails { get; }
}
public class OutTest : ITest
{
public IList<object> SkuDetails { get; set; }
}
Please note that extending property method is supported however opposite of it is not.
Ex:
public interface ITest
{
IList SkuDetails { get; set; }
}
public class OutTest : ITest
{
public IList<object> SkuDetails { get; }
}
is not possible.
My program is starting to get pretty big. and i have found that its starting to do the same thing in multiple area's.
Im trying to figure out how i can make it more efficient.
So i have an object that looks like this
public class TreeViewNode
{
public TreeViewNode()
{
Children = new ObservableCollection<TreeViewNode>();
}
public String Name { get; set; }
public string Description { get; set; }
public ObservableCollection<TreeViewNode> Children { get; set; }
}
i also have another object that looks like this;
public class ComputerObject
{
public String Name { get; set; }
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
public ObservableCollection<Object> Children { get; set; }
}
Both these items need to have some of the same properties..
at the moment they both have the Children Property and the Name Property. but they both need to have some other common properties added to them.
so i have tried something like this.
public class BaseObject
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
public BaseObject()
{
Children = new ObservableCollection<object>();
}
}
public class ComputerObject: BaseObject
{
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
}
public class TreeViewNode: BaseObject
{
public String IconPath { get; set; }
}
Now this is just a cut down version of what i am implementing, i have alot of objects that share the same properties. and some that dont and mix and match. and i cannot figure out the best implimentation for this.
My Objects are becoming very cluttered, and when i rename a property i find that i have to rename it in several area's and this isnt the way its ment to be.
can someone please advise how i would implement multiple objects that share the same property names?
In my opinion you should not let classes inherit from one baseclass when these childclasses are not related to each other (like #Sriram Sakthivel asked Animal < Dog,Cat) just to share the same properties.
You should determine which classes are related (cat, dog are animals; car, motorcycle are vehicles) and then create baseclasses based on these "groupings".
I would look into decorator pattern. In short, you dont share common properties via inheritance. You make classes that contain common properties, and use these classes as properties in your end classes.
EDIT: Example is actually just a standard composition, it should work nevertheless
E.G.
public class Decorator1
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
}
public class Decorator2
{
public long Id { get; set; }
}
public class ClassA
{
public Decorator1 TreeNodeImpl;
}
public class ClassB
{
public Decorator1 TreeNodeImpl;
public Decorator2 LongIdImpl;
}
I have the following model:
public interface IAntiSpam {
string Name { get; }
string Text { get; }
}
public interface IAntiSpamSubclass<T> where T : IAntiSpam {
T Entity { get; set; }
}
public class Comment : IAntiSpam {
public string Name { get; set; }
public string Text { get; set; }
}
public class ForumPost : IAntiSpam {
public User User { get; set; }
public string Text { get; set; }
public string Name { get return User.Name; }
}
public class ReportedData {
public string Reason { get; set; }
public User ReportedBy { get; set; }
public DateTime DateReported { get; set; }
}
public class CommentReported : ReportedData, IAntiSpamSubclass<Comment> {
public Comment Entity { get; set; }
}
public class ForumPostReported : ReportedData, IAntiSpamSubclass<ForumPost> {
public ForumPost Entity { get; set; }
}
This compiles which I take as a sign I'm on the right path.
Now given a List of ReportedData I need to loop over the data and display the Text property against the reported data. I could cast the ReportedData to the appropriate type and then access it from there. However I don't wish to do this as I need to be able to add additional types that inherit from ReportedData without having to modify the code which displays the Text property. This is where I figured my interfaces would help.
Here's the code I've tried to run:
var reportedData = GetReportedData(); // Returns IList<ReportedData>()
foreach (var data in reportedData) {
var text = ((IAntiSpamSubclass<IAntiSpam>)data).Entity.Text;
}
However this gives the following error at run time:
Unable to cast object of type 'CommentReported' to type
'IAntiSpamSubclass`1[IAntiSpam]'.
I'd appreciate it if someone could help show me what I'm doing wrong. Thanks
If the IAntiSpamClass<T> interface is made to be covariant with its type parameter, like this:
public interface IAntiSpamSubclass<out T> where T : IAntiSpam {
T Entity { get; }
}
Then this cast will work. Note these changes:
Added the out modifier on the type parameter.
Removed the property setter.
Further Reading
Variance in Generic Interfaces (C# and Visual Basic)
Creating Variant Generic Interfaces (C# and Visual Basic)
I'm using interfaces in this case mostly as a handle to an immutable instance of an object. The problem is that nested interfaces in C# are not allowed. Here is the code:
public interface ICountry
{
ICountryInfo Info { get; }
// Nested interface results in error message:
// Error 13 'ICountryInfo': interfaces cannot declare types
public interface ICountryInfo
{
int Population { get; }
string Note { get; }
}
}
public class Country : ICountry
{
CountryInfo Info { get; set; }
public class CountryInfo : ICountry.ICountryInfo
{
int Population { get; set; }
string Note { get; set; }
.....
}
.....
}
I'm looking for an alternative, anybody would have a solution?
VB.NET allows this. So, you can create a VB.NET assembly only with the interface definitions that you need:
Public Interface ICountry
ReadOnly Property Info() As ICountryInfo
Public Interface ICountryInfo
ReadOnly Property Population() As Integer
ReadOnly Property Note() As String
End Interface
End Interface
As for the implementation, C# does not support covariant return types, so you must declare your class like this:
public class Country : ICountry {
// this property cannot be declared as CountryInfo
public ICountry.ICountryInfo Info { get; set; }
public class CountryInfo : ICountry.ICountryInfo {
public string Note { get; set; }
public int Population { get; set; }
}
}
If the end goal is to use this with dependency injection, what's wrong with injecting them into each other instead of nesting?
public interface ICountry
{
ICountryInfo Info { get; }
}
public interface ICountryInfo
{
int Population { get; set; }
string Note { get; set; }
}
and implement as:
public class Country : ICountry
{
private readonly ICountryInfo _countryInfo;
public Country(ICountryInfo countryInfo)
{
_countryInfo = countryInfo;
}
public ICountryInfo Info
{
get { return _countryInfo; }
}
}
public class CountryInfo : ICountryInfo
{
public int Population { get; set; }
public string Note { get; set;}
}
Then once you set up your bindings for ICountry & ICountryInfo, CountryInfo will inject into Country whenever Country is injected.
You could then restrict the binding, if you wanted, to only inject CountryInfo into Country and nowhere else. Example in Ninject:
Bind<ICountry>().To<Country>();
Bind<ICountryInfo>().To<CountryInfo>().WhenInjectedInto<Country>();
You can use namespaces like this:
namespace MyApp
{
public interface ICountry { }
namespace Country
{
public interface ICountryInfo { }
}
}
Then in MyApp namespace you can use Country.ICountryInfo which is close to your requirement. Also using alias helps make the code clear.
This will work just fine, no need to nest:
public interface ICountry
{
ICountryInfo Info { get; }
}
public interface ICountryInfo
{
int Population { get; }
string Note { get; }
}
If ICountryInfo has no reason to exist outside ICountry, then why shouldn't you just put the properties of ICountryInfo in ICountry and dismiss the idea of nested interfaces?
An interface that hasn't a meaning of its own without another interface doesn't make sense to me, as an interface on itself is useless if not implemented by a class.