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)
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 am currently working on making viewmodels capable of parsing data extracted from database to the UI and vice versa, and to do so I do a lot of manual mapping between my two viewmodels.
Currently I try to pass some values that determines an attribute, but since each attributetype requires specifying a lot specific parameter, and 90% of the variables will be redundant in all cases since attributes only have one type..
Thus i have create a placeholder base class, which just contains an Id, that each atttribute have,
and each of the specific attribute type parameter will then use this placeholder as base class..
example:
public class BooleanViewSpecification : AttributeTypeSpecification
{
public string TrueOptionText { get; set; }
public string FalseOptionText { get; set; }
}
public class DateTimeTypeViewSpecification : AttributeTypeSpecification
{
public DateTime EarliestDataTime { get; set; }
public DateTime LatestDataTime { get; set; }
}
and my Attribute class is just an
public class AttributeView
{
public DataType Type { get; set; }
public AttributeTypeSpecification AttributeTypeViewSpecification { get; set; }
}
And the same Goes for my DB view model
public class BooleanSpecification : AttributeTypeSpecification
{
public string TrueOptionText { get; set; }
public string FalseOptionText { get; set; }
}
public class DateTimeTypeSpecification : AttributeTypeSpecification
{
public DateTime EarliestDataTime { get; set; }
public DateTime LatestDataTime { get; set; }
}
and my Attribute class is just an
public class Attribute
{
public DataType Type { get; set; }
public AttributeTypeSpecification AttributeTypeSpecification { get; set; }
}
Problem is then mapping from one class to another class
public static IEnumerable<AttributeView> MapToViewModel(this IEnumerable<Attribute> attributes)
{
return attributes.Select(z => new AttributeView()
{
Type = z.Type,
AttributeTypeViewSpecification = z.AttributeTypeSpecification
});
}
Which does not seem to work?
I use entity framework and migrate using Code-First what I receive is the Id of the location, and not the actual values?
I cant seem to understand why I cant be given the values - if it during the mapping does have the value?
So why cant they be mapped over?
I retrieve the value
Context.Include(Attribute).ThenInclude(AttributeTypeSpecification)
The only thing I receive is the actual Id rather than the specified entries?
I am thinking designing a field in db that stores the Serialized Object. When I call that property in entity, that returns String property which is obvious. I am looking for a way to attach a property dynamically and assign the deserialized object to the Class instance. Can any one suggest the best possible way?
DB Structure
Users Table
UserId ..... ..... ..... UserNotes (nvarchar)
Class Structure
[Serializable]
[XmlRoot("Notes")]
public class GenericNotes {
public DateTime Date {
get;
set;
}
public String CommentBy {
get;
set;
}
public string Type {
get;
set;
}
public string Comment {
get;
set;
}
}
public class Users {
public UserId int {
get;
set;
}
public string UserNotes {
get;
set;
}
// I dont have the following definition in the class because its coming from entity framework.
//But I want the following property attached to the class on runtime.
//I will take care of of deserializing using extension methods or some sort methods.
public string List < GenericNotes > NotesCollection {
get;
set;
}
}
Instead of property you can have extension method to do this
public static class UserExtension
{
public static List<GenericNotes> GetNotes(this Users users)
{
//return your deserialized GenericNotes from string
}
}
Then you can use this anywhere like
List<GenericNotes> notes = users.GetNotes();
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.
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