Override the [Required] properties attributes in a wrapper/composition class - c#

There is the following class:
public class A
{
[Required]
public string property { get; set; }
}
and it's used by another class like:
public class B
{
public A prop { get; set; }
public A prop2 { get; set; }
}
in my scenario, B.prop.property should be required while B.prop2.property should not be [Required].
Is there a way to override prop2.property attribute to be not required? and it also should affect the record recorded in the Database?
if not what is the most recommended practice to deal with such issue?

No. There is no way to achieve what you're talking about. You can do so via inheritance. For example:
public class C : A
{
public new string property { get; set; }
}
Then:
public class B
{
public A prop { get; set; }
public C prop2 { get; set; }
}
In other words, the property must literally be a type where that property is not required. You can't just disable an attribute on a class instance at a whim.

Related

Interface with a list of interface, how to choose one type implemented by interface

This is my first question on StackOverflow, so please forgive and tell me if I'm doing something wrong.
Problem:
I write some kind of dictionary connected to DB and text files etc. nothing commercial, just learning. For better explanation it can be English-French.
I want to refactor the code to have possibility of use one "general" method to process entrance for English-French and French-English dictionary model. On the begining i made separate model for each of them(I will paste if necessary) and now i would like to make everything "universal". What I did till i stop:
public interface IWordModel
{
int Id { get; set; }
string Name { get; set; }
string Definition { get; set; }
}
class implementing IWordModel:
public class EnglishWordModel: IWordModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Definition { get; set; } = null;
}
public class FrenchWordModel : IWordModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Definition { get; set; } = null;
}
Interface implementing IWordModel and problematic List of this interface:
public interface IDictionairyModel<T> where T : IWordModel
{
int Id { get; set; }
T BaseWord { get; set; }
List<T> DerivativeWords { get; set; }
}
Class implementing IDicionairyModel
public class EnglishFrenchDictionairyModel<T>: IDictionairyModel where T : IWordModel
{
public int Id { get; set; }
public IWordModel BaseWord { get; set; } = new EnglishWordModel();
public List<IWordModel> DerivativeWords { get; set; } = = new
List<IWordModel>(new List<FrenchWordModel>());
}
public class FrenchDictionairyModel: IDictionairyModel<T> where T : IWordModel
{
public int Id { get; set; }
public IWordModel BaseWord { get; set; } = new FrenchWordModel();
public List<IWordModel> DerivativeWords { get; set; } = = new
List<IWordModel>(new List<EnglishWordModel>());
}
And my Question
How to make that i.e in FrenchDictionairyModel instance we will be able to define BaseWord only as FrenchWordModel and add to DerivativeWords list ONLY EnglishWordModel? I know it have something common with covariance and contrvariance but i dont have idea how to apply this here.
Is it above code have some sense from experienced coder point of view or it's look like OK only in my head? If answer is NO then how it should look like, what pattern should i use?
How to use it properly in other methods? As now i was using i.e
public List<EnglishFrenchDictionairyModel>
CreateEnglishFrenchEntrance(List<EnglishFrenchDictionairyModel> model){
( ... )}
but its already showing "Using generic type requires 1 type arguments".
Thanks and have a Great Day!
It sounds like you need two generic parameters - one to apply to BaseWord and one to apply to DerivativeWords:
public interface IDictionairyModel<T,U>
where T : IWordModel, U : IWordModel
{
int Id { get; set; }
T BaseWord { get; set; }
List<U> DerivativeWords { get; set; }
}
Then define your FrenchDictionaryModel as so:
public class FrenchDictionairyModel:
IDictionairyModel<FrenchWordModel, EnglishWordModel>
{
public int Id { get; set; }
public FrenchWordModel BaseWord { get; set; } = new FrenchWordModel();
public List<EnglishWordModel> DerivativeWords { get; set; } = new List<EnglishWordModel>();
}
Thanks D Stanley! it works fine, just need to add two where clauses for U and T like:
public interface IDictionairyModel<T,U>
where T : IWordModel,
where U : IWordModel {(...)}
But now i have another issue which i would like to implement here.
For example i would like to create some method which will be remove duplicates from List but i want to this to be ONE method for all class which implementing IDictionairyModel
public static List<IDictionairyModel<IWordModel, IWordModel>> RemoveDuplicates(this List<IDictionairyModel<IWordModel, IWordModel>> model)
{
(...) return model;
}
What I need to do to be able to use this extension method on
List<FrenchDictionairyModel> model = new List<FrenchDictionairymodel>();
model.RemoveDuplicates();
As for now it return error.
Should I make FrenchDictionairyModel also generic like:
public class PoznanPolishDictionairyModel<T,U> : IDictionairyModel<PoznanWordModel, PolishWordModel>
where T:IWordModel
where U:IWordModel
??? What is the proper way
Thanks a lot!!!
Have a wonderful Sunday!
Best Regards

Mapping with Automapper and Underscores

In the below example, I'm just trying to get Test_Person_Name.FirstName to map to something (anything) in TestPersonFlattened. At this point, considering the amount of time I've sunk into this, I'm not too hung up on what the destination property name is..I just want it to work.
public class Test_Person
{
public Test_Person_Name Test_Person_PublicName { get; set; }
}
public class Test_Person_Name
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class TestPersonFlattened
{
public string Test_Person_PublicNameFirstName { get; set; } // What do I call this property?
}
AutoMapper.Mapper.CreateMap<Test_Person, TestPersonFlattened>();
AutoMapper.Mapper.AssertConfigurationIsValid();
It seems like Test_Person_PublicNameFirstName should work, but I get an exception on AssertConfigurationIsValid(). I've also tried TestPersonPublicNameFirstName, Test_Person_PublicName_FirstName as destination property names.
It'd be unfavorable to rename the source property name, just because the source library is used in many other projects. Also, a ForMember() call isn't ideal, but I'll do it if there's no other option.
One way to do it would be to simply leave out "Test_Person_" from the PublicNameFirstName property of your TestPersonFlattened class, and use RecognizePrefixes() to make it so that AutoMapper ignores "Test_Person_" when attempting to map property names.
The following code succeeds:
public partial class App : Application
{
public App()
{
Mapper.Initialize(cfg =>
{
cfg.RecognizePrefixes("Test_Person_");
cfg.CreateMap<Test_Person, TestPersonFlattened>();
});
Mapper.CreateMap<Test_Person, TestPersonFlattened>();
Mapper.AssertConfigurationIsValid();
}
}
public class Test_Person
{
public Test_Person_Name Test_Person_PublicName { get; set; }
}
public class Test_Person_Name
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class TestPersonFlattened
{
public string PublicNameFirstName { get; set; } // This is what I call this property!
}

c# public property inaccessible

[DataContract]
public class UniqueNamedItem
{
[DataMember]
int Id { public get; protected set; }
[DataMember]
string Name { public get; protected set; }
}
[KnownType(typeof(UniqueNamedItem))]
[DataContract]
public class BasicNode : UniqueNamedItem
{
[DataMember]
SortedList<string, BasicNode> Children { public get; private set; }
public void addChild(BasicNode bn)
{
this.Children.Add(bn.Name, bn);
}
}
Can you tell me why inside my addChild function the call to bn.Name is not valid even though the UniqueNamedItem.Name property has a public get accessor?
The default accessibility for members of classes is private.
So Id and Name are private.
You need to add the correct access modifiers (I added public, you may have meant protected):
[DataContract]
public class UniqueNamedItem
{
[DataMember]
public int Id { public get; protected set; }
[DataMember]
public string Name { public get; protected set; }
}
One good reason to always declare the accessibility you want.
The UniqueNamedItem.Name property itself is private; you need to explicitly mark the property as public.
The modifiers on accessors can only restrict access further, not increase it.
You need to declare your properties as public (see below). The default is private.
[DataContract]
public class UniqueNamedItem
{
[DataMember]
public int Id { public get; protected set; }
[DataMember]
public string Name { public get; protected set; }
}
You need to make your properties public:
[DataContract]
public class UniqueNamedItem
{
[DataMember]
public int Id { public get; protected set; }
[DataMember]
public string Name { public get; protected set; }
}
Your properties are not explicitly marked as public, thus C# automatically considers them to be private.
So:
[DataContract]
public class UniqueNamedItem
{
[DataMember]
int Id { public get; protected set; }
[DataMember]
public string Name { public get; protected set; }
}
The default access is private, because if you make something public when it should really be private, it won't stop any correct code from working, and it could be that way for years before you realise (and it's also a breaking change to then fix it).
If on the other hand you make something private when it should be public, something will stop working immediately, you go on stackoverflow, a bunch of people say it's private, you fix it, and all is well.
Hence it's a sensible default.

How do I organize C# classes that inherit from one another, but also have properties that inherit from one another?

I have an application that has a concept of a Venue, a place where events happen. A Venue has many VenueParts. So, it looks like this:
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<VenuePart> VenueParts { get; set; }
}
A Venue can be a GolfCourseVenue, which is a Venue that has a Slope and a specific kind of VenuePart called a HoleVenuePart:
public class GolfCourseVenue : Venue
{
public string Slope { get; set; }
public virtual ICollection<HoleVenuePart> Holes { get; set; }
}
In the future, there may also be other kinds of Venues that all inherit from Venue. They might add their own fields, and will always have VenueParts of their own specific type.
Here are the VenuePart classes:
public abstract class VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public override string NameDescriptor { get { return "Hole"; } }
public int Yardage { get; set; }
}
My declarations above seem wrong, because now I have a GolfCourseVenue with two collections, when really it should just have the one. I can't override it, because the type is different, right? When I run reports, I would like to refer to the classes generically, where I just spit out Venues and VenueParts. But, when I render forms and such, I would like to be specific.
I have a lot of relationships like this and am wondering what I am doing wrong. For example, I have an Order that has OrderItems, but also specific kinds of Orders that have specific kinds of OrderItems.
Update: I should note that these classes are Entity Framework Code-First entities. I was hoping this wouldn't matter, but I guess it might. I need to structure the classes in a way that Code-First can properly create tables. It doesn't look like Code-First can handle generics. Sorry this implementation detail is getting in the way of an elegant solution :/
Update 2: Someone linked to a search that pointed at Covariance and Contravariance, which seemed to be a way to constrain lists within subtypes to be of a given subtype themselves. That seems really promising, but the person deleted their answer! Does anyone have any information on how I may leverage these concepts?
Update 3: Removed the navigation properties that were in child objects, because it was confusing people and not helping to describe the problem.
Here's one possible option using generics:
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public string NameDescriptor { get{return "I'm a hole venue"; } }
}
public class Venue<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
}
Here GolfCourseVenue has the collection VenueParts, which can contain HoleVenueParts or super classes HoleVenueParts. Other specializations of Venue would restrict VenueParts to containing VenueParts specific to that venue.
A second possibility is pretty much as you had it
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public string NameDescriptor { get{return "I'm a hole venue"; } }
}
public class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<VenuePart> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue
{
}
Now GolfCourseVenue has the collection VenueParts, which can contain VenueParts or super classes VenueParts. Here all specializations of Venue can contain any type of VenuePart which may or may not be appropriate.
In answer to your comment about covariance, I would propose something like this:
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public override string NameDescriptor { get{return "I'm a hole venue"; } }
}
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public abstract ICollection<VenuePart> VenueParts { get; }
}
public class GolfCourseVenue : Venue
{
private ICollection<HoleVenuePart> _holeVenueParts;
public GolfCourseVenue(ICollection<HoleVenuePart> parts)
{
_holeVenueParts = parts;
}
public override ICollection<VenuePart> VenueParts
{
get
{
// Here we need to prevent clients adding
// new VenuePart to the VenueParts collection.
// They have to use Add(HoleVenuePart part).
// Unfortunately only interfaces are covariant not types.
return new ReadOnlyCollection<VenuePart>(
_holeVenueParts.OfType<VenuePart>().ToList());
}
}
public void Add(HoleVenuePart part) { _holeVenueParts.Add(part); }
}
I look forward to the advice of others - but my approach is to use generics in this case. With generics, your GolfCourseVenue's "parts" are strong typed!
...and as I type this everyone else is saying generics too. HOW DO YOU overstackers type so dang fast?!
Anyways, pretending I'm still first -
public class VenuePart
{
}
public class HoleVenuePart : VenuePart
{
}
public abstract class Venue<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> Parts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
public string Slope { get; set; }
}
Also, as a 2nd option, you could use an interface too, so in case you didn't like the name Parts, you could call it Holes when the derived type is known to be a GolfCourse
public class VenuePart
{
}
public class HoleVenuePart : VenuePart
{
}
public interface IPartCollection<T> where T : VenuePart
{
ICollection<T> Parts { get; set; }
}
public abstract class Venue<T> : IPartCollection<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> Parts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
public string Slope { get; set; }
ICollection<HoleVenuePart> IPartCollection<HoleVenuePart>.Parts { get { return base.Parts; } set { base.Parts = value; }}
public virtual ICollection<HoleVenuePart> Holes { get { return base.Parts; } set { base.Parts = value;}}
}
You can use Covariance
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual IEnumerable<VenuePart> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue
{
public string Slope { get; set; }
public GolfCourseVenue()
{
List<HoleVenuePart> HoleVenueParts = new List<HoleVenuePart>();
HoleVenueParts.Add(new HoleVenuePart());
VenueParts = HoleVenueParts;
}
}
Assuming HoleVenuePart is inherited from VenuePart
If you remove "set" portions of both collections than it will make more sense: base class provides "all parts" collection, while derived classes have filtered view in addition to base class one.
Note: Depending on your needs making GolfVenue to be specialization generic of Venue<VenuePart> may not work as Venue<Type1> and Venue<Type2> will not have any good base class to work with.
Consider using interfaces instead of base classes as it would allow more flexibility in implementation.
public interface IVenue
{
public int Id { get; }
public string Name { get; }
public virtual IEnumerabe<VenuePart> VenueParts { get; }
}
public interface IGolfCourse : IVenue
{
public virtual IEnumerabe<HoleVenuePart> Holes { get; }
}
Now you can use GolfCourse:Venue from other samples but since it implements interface you can handle it in gnereic way too:
class GolfCourse:Venue<HoleVenuePart>, IGolfCourse {
public virtual IEnumerabe<VenuePart> Holes{ get
{
return VenueParts.OfType<HoleVenuePart>();
}
}
}
class OtherPlace:Venue<VenuePart>, IVenue {...}
List<IVenue> = new List<IVenue> { new GolfCourse(), new OtherPlace() };
Nothe that GolfCourse and OtherPlace don't have common parent class (except object), so without interface you can't use them interchangebly.

NHibernate 'Bags' Implementation in Entity Framework

I started using EF with Code First recently and have come upon this issue which has left me rather perplexed. I will appreciate any feedback on this topic which will help me in resolving the said issue.
Please consider the following sample....
public class SomeType
{
public SomeType()
{
Properties = new List<BaseProperty>();
}
public int PrimaryKey { get; set; }
public string Name { get; set; }
public List<BaseProperty> Properties { get; set; }
}
public abstract class BaseProperty
{
public int PrimaryKey { get; set; }
public string PropertyName { get; set; }
// FK set through Type Configuration File.
public SomeType ParentInstance { get; set; }
}
public class PropertyA : BaseProperty
{
// some unique properties.
}
public class PropertyB : BaseProperty
{
// some unique properties.
}
public class PropertyC : BaseProperty
{
// some unique properties.
}
public class PropertyD : BaseProperty
{
// some unique properties.
}
All of this works great with the appropriate type configuration classes which map to 2 tables (1 for 'SomeType' and the second for 'BaseProperty' along with the remaining derived entities through the use of a discriminator column).
Now, due to circumstances beyond my control, I am being forced to modify 'SomeType' to something like this....
public class SomeType
{
public SomeType()
{
PropertiesAB = new List<BaseProperty>();
PropertiesC = new List<PropertyC>();
PropertiesD = new List<PropertyD>();
}
public int PrimaryKey { get; set; }
public string Name { get; set; }
public List<BaseProperty> PropertiesAB { get; set; } // collection of PropertyA and PropertyB
public List<PropertyC> PropertiesC { get; set; } // collection of PropertyC
public List<PropertyD> PropertiesD { get; set; } // collection of PropertyD
}
This would be very fairly easy to do in NHibernate using bags but is there an equivalent implimentation for this in EF using Code First ? Any thoughts ?
I do not want to write my own implimentation of a Collection which will forward and manipulate all operations to be performed on these new lists to a master list which will be actually mapped to the database.
Please ignore any missing "virtual" modifiers or anything else in the above code since it is only meant to be a sample and is NOT actually what I am using.
Thank you for your replies.
Worse comes to Worse, you can do something like this:
public class SomeType
{
public SomeType()
{
Properties = new List<BaseProperty>();
}
public int PrimaryKey { get; set; }
public string Name { get; set; }
public List<BaseProperty> Properties { get; set; }
public List<BaseProperty> PropertiesAB
{
get
{
return Properties.Where(p=>p is PropertyA || p is PropertyB);
}
set
{
//Remove all the properties already in the Properties collection of
//the type A and B and then
Properties.AddRange(value)
}
}
//Same with rest of the properties
}
You can also make the Properties property internal if the class is being used outside the domain layer

Categories