I am having a question, and probably it can not be done this way but maybe there is some other way i do not know, so I have a class that looks like this:
[DataContract]
public class Parent
{
[DataMember(Name="id")]
public int Id { get; set; }
[DataMember(Name = "value")]
public int Value { get; set; }
}
Now this class is a attribute value of different class:
[DataContract]
public class Location
{
[DataMember(Name="parent")]
public Parent Parent { get; set; }
}
But there is a catch, I need separate classes bout same type for example:
[DataContract]
public class Parent
{
[DataMember(Name="id")]
public int Id { get; set; }
}
[DataContract]
public class Parent
{
[DataMember(Name = "value")]
public int Value { get; set; }
}
Depending if Value is null or not (and I need this to be separate object cause as you see I want to map this). Is it possible to overwrite class so one class can have one or other attribute only?
You could solve it with inheritance, but IMHO it gets overdesigned.
Personally, I would all put into the Parent class. Make the properties nullable, than it's done. If you want to have some reliability that at least one property is set, you may want to make the setters private (given that you don't need to change them after creating the parent) and have factory methods to create parents with an Id or a Value.
Parent with encapsulation (if required):
[DataContract]
public class Parent
{
private Parent() {}
[DataMember(Name="id")]
public int? Id { get; private set; }
[DataMember(Name = "value")]
public int? Value { get; private set; }
public static Parent CreateWithId(int id)
{
return new Parent { Id = id };
}
public static Parent CreateWithValue(int value)
{
return new Parent { Value = value };
}
}
You can further add a ParentType property which returns an enum value which is either ParentType.ValueParent or ParentType.IdParent. Again, this is only useful when required, e.g. because it simplifies handling of parents, when there is a chance to get more different types or when you may want to support Id Parents with a null value as Id or the same with the Value.
Completely different solution is to store both Id and Value in the same property, since both are integers. Have another way to distinguish wether it is a Id or a Value.
[DataContract]
public class Parent
{
[DataMember(Name="id")]
public int Data { get; private set; }
[DataMember(Name="id")]
public ParentType ParentType { get; private set; }
public static Parent CreateWithId(int id)
{
return new Parent { Data = id, ParentType = ParentType.Id };
}
public static Parent CreateWithValue(int value)
{
return new Parent { Data = value, ParentType = ParentType.Value };
}
}
You're trying to represent DIFFERENT data by creating two different classes which are named the same. This is an error. Initially I wanted to suggest using interfaces or inheritance, but that makes no sense, as both Parent classes you wrote contain different things and there's no overlap.
If this case is directed purely because you need to map those properties to some data contract, then why not have a Parent class with both properties and just make those properties Nullable?
Something along the lines:
[DataContract]
public class Parent
{
[DataMember(Name="id")]
public int? Id { get; set; }
[DataMember(Name = "value")]
public int? Value { get; set; }
}
1 As said HimBromBree, you can put Parent classes in different namespaces.
WCF also allows you to provide different names for Serialization of classes through [DataContract] attribute :
[DataContract(Name="ParentA")]
public class Parent {
[DataMember(Name="id")]
public int Id { get; set; }
}
2 If your goal is to have Parent class to hold different values (Value or Id) depending on circumstances, you can also create two derived classes of Parent.
Let's call those classes ParentA and ParentB
Then on Parent, you should make a declaration for polymorphic serialization :
[DataContract]
[KnownType(typeof(ParentA))]
[KnownType(typeof(ParentB))]
public class Parent {}
[DataContract(Name="ParentA")]
public class ParentA : Parent {
[DataMember(Name="id")]
public int Id { get; set; }
}
Related
I have:
Entity Framework DB first
public partial class Departments
{
public string Name_Department { get; set; }
public int Department_ID { get; set; }
}
When i was refreshed model all modify in file was cleared
I need:
How can i add attribute property to Serialize XML like:
[Serializable]
[XmlType(nameof(Departments))]
public partial class Departments
{
[XmlAttribute("Name_Department")]
public string Name_Department { get; set; }
[XmlAttribute("Department_ID")]
public int Department_ID { get; set; }
}
You have to make the generated properties private in the properties window. Then you have to create new public properties that reference the private properties and add the attributes to them. In the properties window you can also rename your now private properties so that you can name your public properties like the original ones:
Generated code:
public partial class Departments
{
private string Name_DepartmentCore { get; set; }
private int Department_IDCore { get; set; }
}
Custom code (in C# 7.0):
[Serializable]
[XmlType(nameof(Departments))]
public partial class Departments
{
[XmlAttribute("Name_Department")]
public string Name_Department {
get => Name_DepartmentCore;
set => Name_DepartmentCore = value;
}
[XmlAttribute("Department_ID")]
public int Department_ID {
get => Department_IDCore;
set => Department_IDCore = value;
}
}
Your class model is generated when you are using DB first, that is by design.
Solution 1. Microsoft is dropping support for database first, and edmx is depricated. One solution would be to use CODE FIRST instead. This would allow you to decorate your POCO classes with attributes.
Solution 2. Create a parallel model just for XML serialization.
I have a generic class with a single argument that represents an Element of a third party DLL for the purpose of serialization of objects of T kind. What I would like to do is add a 'Dirty' map to my class and lazily trigger it whenever one of my Element's nested properties are changed.
Is it possible to when the property is accessed catch the request and identify what property is changing? That if a SET is being performed I can log that sub-property P is now dirty and needs to be saved? Or at least a single bit that indicates that SOMETHING has changed?
public class ResourceSerializer<T>
where T : Base, new()
{
T element;
Dictionary<String,Boolean> dirtyMap;
public T Element { get { return this.getElement(); } }
public Boolean IsDirty { get; private set; }
public ResourceSerializer()
{
dirtyMap = new Dictionary<string,bool>();
element = new T();
// code to reflect back upon T's Properties and build out the dirtyMap.
// I already can do this I just omitted it.
// in my Person example there would be keys: 'FirstName', 'LastName', 'Age', 'Gender', 'PrimaryAddress'
}
// how can I call this programmatically?
void flagDirty(String property)
{
dirtyMap[property] = true;
this.IsDirty = true;
}
T getElement()
{
// In case I need to do a thing before returning the element.
// Not relevant to the question at hand.
return this.element;
}
}
a somewhat advanced example of 'Base'. You can see how I need to recurse my actions as not everything is a primitive. I have a manager level class that logs all of these ResourceSerializer objects.
public class Base
{
public Base()
{
}
}
public enum gender
{
Male,
Female,
Other,
Unspecified,
}
public class Address : Base
{
public String Street { get; set; }
public String State { get; set; }
public String Zip { get; set; }
public Address() : base()
{
}
}
public class Person : Base
{
public String FirstName { get; set; }
public String LastName { get; set; }
public Int16 Age { get; set; }
public gender Gender { get; set; }
public Address PrimaryAddress { get; set; }
public Person() : base()
{
}
}
public class Patient : Person
{
public Person PrimaryContact { get; set; }
public Patient() : base()
{
}
}
and a small class i would turn into a test method later..
public class DoThing
{
public DoThing()
{
ResourceSerializer<Person> person = new ResourceSerializer<Person>();
person.Element.Age = 13; // catch this and mark 'Age' as dirty.
}
}
Without a custom setter no, there's nothing to do that.
The usual pattern for what you're trying to do is implement the INotifyPropertyChanged interface, that interface is precisely created for classes (or structs) which need to track and inform about changes on their properties.
If you're lazy as me, I would create an analyzer which at the beginning of my app scans all my classes which are tagged with an attribute and with all properties created as virtual, then using codedom I would create a new class which would inherit from the found class and it implements the INotifyPropertyChanged, then you can have a generic Factory which returns instances of these new classes when the type of the generic call is of a known registered type.
I've used this before for classes which I wanted to have remote properties, just tagged the class and my scan system rewrote the getter/setter to do the remote calls transparently, the concept at the end is the same.
It's a lot of work at the begining, but if you have a ton of classes it will be a lot less of code to write than implementing INotifyPropertyChanged on all your classes.
I want to have below class properties to be displayed in PropertyGrid not in the declared order, instead specified attribute? is there such attribute for?
As:
A
B
C
Thanks.
public class ApplicationConfiguration
{
public ApplicationConfiguration()
{
}
public int A { get; set; }
public int C { get; set; }
public int B { get; set; }
}
If you are sending this object from an MVC/WCF application you can use DataMember attribute like below
public class ApplicationConfiguration
{
public ApplicationConfiguration()
{
}
[DataMember(Order=1)]
public int A { get; set; }
[DataMember(Order = 3)]
public int C { get; set; }
[DataMember(Order = 2)]
public int B { get; set; }
}
You have many options in deciding how instances of your classes should appear in the property grid. Start off with Design-Time Attributes for Components and go from there.
See Extending Design-Time Support for the big picture. The bottom line is that you can easily cause your properties to display grouped by categories just by adding [Category("categoryName")] attributes. But if you need them to appear in a completely different order from their order of declaration, then you need to create a Designer.
Let's assume the following, simplified, class structure:
public class Parent
{
public int ID { get; set; }
}
public class ChildA : Parent
{
public string Name { get; set; }
}
public class ChildB : Parent
{
public DateTime Date { get; set; }
}
public class ChildC : Parent
{
public int NumericData { get; set; }
}
public class ViewModel
{
public List<Parent> ChildElements { get; set; }
}
As you can see, in my view model I have a list of objects, but these objects can be of different types.
Now, I've found that editor templates work well in this scenario - #Html.EditorFor() selects the right editor as needed depending on the type of the element in the list.
I am, however, having trouble getting meaningful data back from the user to the controller. Upon submitting the form, the view-model contains a list of Parent elements (not the specific sub-types). Worse - the properties specific to each of the Child classes is lost!
What can I do to get all the information for the subtypes back to the controller?
When data is posted by to the controller, the MVC framework handles the binding of the request data to your model. Have a look at this link
When it is trying to instantiate your ViewModel, it is probably using the default parameterless constructor for your Parent class, and whatever the actual data being sent back, it cannot assign it to the properties as they don't exist within the Parent class.
You can create your own custom model binder which might solve your problem. Or you could potentially create all the properties in the Parent class, and have different named EditorTemplates.
#Html.EditorFor(x => Model.Parent, "ChildATemplate")
#Html.EditorFor(x => Model.Parent, "ChildBTemplate")
As a general rule it is a good idea to stick to the rule, "One View, One ViewModel", even if it feels like duplication at first. It makes it clear exactly what data is being sent out from the server and exactly what data is being returned.
If 'Parent' represents a complex object, perhaps one that that is persisted into a database and is interacted with from several views, then you can always have an intermediate tier which handles converting data from the view model to your complex class.
EDIT - in response to comment regarding survey questions
Rather than using inheritance, why not accept that you need to duplicate a little of the shared values, and create a class for each question type?
public class QuestionTypeA
{
public int ID { get; set;}
public string Name { get; set; }
}
public class QuestionTypeB
{
public int ID { get; set;}
public DateTime Date { get; set; }
}
public class QuestionTypeC
{
public int ID { get; set;}
public int NumericData { get; set; }
}
public class ViewModel
{
public List<QuestionTypeA> QuestionAs { get; set; }
public List<QuestionTypeB> QuestionBs { get; set; }
public List<QuestionTypeC> QuestionCs { get; set; }
}
I have a class, "Search". See definition below:
public class Search
{
[Key]
public int SearchID { get; set; }
public int UserID { get; set; }
public SearchParameters SearchParameters { get; set; }
public ICollection<SearchProvider> SearchProviders { get; set; }
public User User;
}
SearchParameters is a class with value types, and a few sub-classes; as defined below:
public class SearchParameters
{
public List<string> SearchTerms { get; set; }
public int MaxRecords { get; set; }
public DistanceParameter Distance { get; set; }
public PriceRangeParameter PriceRange { get; set; }
}
The idea is that I do not want a separate SearchParameters table that has to link to the Search table because every property of the search is always one to one (Except for SearchTerms). Really, what I want EF to do is 'bring up' the child classes' properties so we end up with All the properties of SearchParameter in the SearchTable (and all the parameters of the DistanceParameter and PriceRangeParameter objects themselves). What annotations or other logic would I need for this to work? Thanks!
I think EF Complex Type mapping is what you need, see more here:
http://weblogs.asp.net/manavi/archive/2011/03/28/associations-in-ef-4-1-code-first-part-2-complex-types.aspx