WCF CollectionDataContract Dictionary constructor - c#

I'm using a WCF CollectionDataContract to pass data using a Dictionary and it is working very well.
[CollectionDataContract]
public class MyDataDictionary : Dictionary<string, MyItemValue> { }
[DataContract]
public class MyItemValue
{
[DataMember] public int ID { get; set; }
[DataMember] public string Name { get; set; }
// ...
public IP21ItemValue() {
ID = -1;
Name = string.Empty;
// ...
}
}
I want to enhance my dictionary so it is case insensitive and I've tried a variety of things similar to these:
// Attempt to put the argument on the declaration.
[CollectionDataContract]
public class MyDataDictionary : Dictionary<string, MyItemValue>(StringComparer.InvariantCultureIgnoreCase) { }
// Attempt to instantiate it within the constructor...
[CollectionDataContract]
public class MyDataDictionary : Dictionary<string, MyItemValue> {
public MyDataDictionary() {
this = new Dictionary<string, MyItemValue>(StringComparer.InvariantCultureIgnoreCase);
}
}
But I can't seem to make anything work. I'd really like to avoid wrapping the whole thing in a class where the dictionary is a data member. Is there a syntax that will do this?

Call the base class constructor, like this:
public class MyDataDictionary : Dictionary<string, MyItemValue> {
public MyDataDictionary()
:base(StringComparer.InvariantCultureIgnoreCase)
{
}
}

Related

C# - CS0572 Error When Trying to Populate a Class

C# Newbie Here.
I have a class below:
namespace CompanyDevice.DeviceResponseClasses
{
public class DeviceStatusClass
{
public class Root
{
public static string RequestCommand { get; set; }
}
}
}
In another namespace I have:
namespace CompanyDevice
{
public class StatusController : ApiController
{
public DeviceStatusClass Get()
{
var returnStatus = new DeviceStatusClass();
returnStatus.Root.RequestCommand = "Hello"; //'Root' is causing a CS0572 error
return returnStatus;
}
}
}
I'm sure I'm making some rudimentary error here. Could you please help me find it? Thanks.
You access static properties from the type, not from the instance.
DeviceStatusClass.Root.RequestCommand = "Command";
Because the property RequestCommand is static, there will only ever be one. Perhaps this is what you want, but likely is not based on your usage.
You can remove the static keyword from RequestCommand, then you can access it through the instance, however you will need to add a field or property for the instance of Root inside of DeviceStatusClass.
public class DeviceStatusClass
{
public Root root = new Root();
public class Root
{
public string RequestCommand { get; set; }
}
}
And use like you did originally.
public class StatusController : ApiController
{
public DeviceStatusClass Get()
{
var returnStatus = new DeviceStatusClass();
returnStatus.root.RequestCommand = "Hello";
return returnStatus;
}
}
You maybe have a java background. In c# nested classes only change the names, they do not make the parent class contain an instance of a child class
namespace CompanyDevice.DeviceResponseClasses
{
public class DeviceStatusClass
{
public class Root
{
public static string RequestCommand { get; set; }
}
public Root DeviceRoot {get;set;} <<<=== add this
}
}
and then
returnStatus.DeviceRoot.RequestCommand = "Hello";

Serialize ValueObject as XML

You would think this is a very simple question. But after lots of searching and testing I have not found a pretty solution.
As per domain driven design I created strongly typed identifier classes. Because that helps with validation and not accidentally mixing up identifiers.
So I made a simple base class like so:
public abstract class UIDBase<T>
{
private readonly T _id;
protected UIDBase(T id)
{
_id = id;
}
public T ID
{
get { return _id; }
}
// Plus hash/equals implementation
}
And simple implementations like so:
public class SensorUID : UIDBase<string>
{
public SensorUID(string id) : base(id)
{
}
}
And then I use it:
public class SomeObject
{
public SensorUID SensorUID { get; set; }
public FileName FileName { get; set; }
}
But now when I serialize it as XML, I need a default constructor (annoying). But worse, the properties are no longer serialized as attributes.
Preferable I only want to add custom Xml serialisation code to my UIDBase class. Adding attributes or implementing an interface to tell the xml serializer that these classes should be serialized as attributes. Just like string/int/long etc.
If those value types can do it, why not my own value type?
The Xml should look like:
<SomeObject SensorUID="X" FileName="Y"/>
This seems to work, but it feels ugly:
public class SomeObject
{
[XmlIgnore]
public SensorUID SensorUID { get; set; }
[XmlIgnore]
public FileName FileName { get; set; }
[XmlAttribute("SensorUID")]
public string SensorUIDAsString
{
get { return SensorUID == null ? null : SensorUID.ID; }
set { SensorUID = new SensorUID(value); }
}
[XmlAttribute("FileName")]
public string FileNameAsString
{
get { return FileName == null ? null : FileName.ID; }
set { FileName = new FileName(value); }
}
}

Structure for Classes containing Lists of Instantiated classes to be stored in Dictionary

For my example classes to be stored are lets say:
class Race
{
public string Name { get; set; }
public DateTime Date { get; set; }
public List<Competitor> Competitors = new List<Competitor>();
}
class Competitor
{
public string Name { get; set; }
public List<Stats> SomeData = new List<Stats>():
}
class Stats
{
//Other Properties Etc
}
They are to be stored in :
class Events : Dictionary<string, List<Race>>
{
public Events()
: base()
{
}
}
And I fill the Dictionary with another class :
class GenerateEventsData
{
public Events newEvents = new Events();
public GenerateEventsData()
{
fillEvents();
}
private void fillEvents()
{
//Method to fill events.
}
}
I feel as though I'm getting to a stage where lists of classes are being stacked up and my structure is not correct.
I plan to eventually serialize the data to disk and re-use at a later date but that's beyond the bounds of this question. However if the classes aren't well structured i think i may have issues.
Thanks in advance.
you could use a generic container:
public class ListDictionary<T> : Dictionary<string,List<T>>
{
public ListDictionary():base(){}
public void AddItem(string key, T value)
{
if(ContainsKey(key))
this[key].Add(value);
else
Add(key,new List<T>{value});
}
//similar for remove and get
}
Also have a look at the repository pattern.

Automapper automatically resolve correct subclass to map to?

Given the following source types:
public class BaseViewModel
{
public string Prop1 { get; set; }
}
public class FirstViewModelImpl : BaseViewModel
{
public string Prop2 { get; set; }
}
public class SecondViewModelImpl : BaseViewModel
{
public string AnotherProp { get; set; }
}
And the following destination types
public class BaseDto
{
public string Prop1 { get; set; }
}
public class FirstDtoImpl : BaseDto
{
public string Prop2 { get; set; }
}
public class SecondDtoImpl : BaseViewModel
{
public string AnotherProp { get; set; }
}
With the following mappings:
Mapper.CreateMap<FirstViewModelImpl,FirstDtoImpl>();
Mapper.CreateMap<SecondViewModelImpl,SecondDtoImpl>();
Can I do the following (trivial example) - given that I don't actually know the type of viewmodel until runtime?
BaseViewModel myViewModel = GetAViewModelFromSomewhere();
FirstDtoImpl dto = (FirstDtoImpl)Mapper.Map<BaseViewModel,BaseDto>(myViewModel);
I am trying this out now anyway!
I have found that if I change the mappings to
Mapper.CreateMap<BaseViewModel,BaseDto>()
.Include<FirstViewModelImpl,FirstDtoImpl>()
.Include<SecondViewModelImpl,SecondDtoImpl>();
Mapper.CreateMap<FirstViewModelImpl,FirstDtoImpl>();
Mapper.CreateMap<SecondViewModelImpl,SecondDtoImpl>();
Then it works as expected without using the type converter.
You can't do that directly, however you can work around it with a TypeConverter.
In the Mappings you will add:
Mapper.CreateMap<BaseViewModel, BaseDto>()
.ConvertUsing<MyTypeConverter>();
Then you can create the converter like so:
public class MyTypeConverter : TypeConverter<BaseViewModel, BaseDto>
{
protected override BaseDto ConvertCore(BaseViewModel tViewModel)
{
BaseDto vResult = null;
if(tViewModel is FirstViewModelImpl)
{
var vSource = tViewModel as FirstViewModelImpl;
vResult = Mapper.Map<FirstViewModelImpl,FirstDtoImpl>(vSource);
}
else if(tViewModel is SecondViewModelImpl )
{
var vSource = tViewModel as SecondViewModelImpl ;
vResult = Mapper.Map<SecondViewModelImpl ,SecondDtoImpl>(vSource);
}
return vResult;
}
}
Then you can use it like:
BaseDto dto= Mapper.Map<BaseViewModel,BaseDto>(myViewModel);
and have dto actually be of the type you wanted.
It won't map the Base types to each other though. If that matters I can twist it a bit more.
Can you use an interface instead? Also, there is a non-generic Mapper.Map implimentation that might work better in this case. If you have the mapping set up, you can just pass in the type.
No this is not correct if you create Mapping for derived types you should when
map objects specify the derived class also

Default object implementation

I want to implement default object pattern for my all classes in the inheritance tree. I am doing as shown below.
namespace test
{
public class Record
{
public int ID { get; set; }
}
public class StudentRecord : Record
{
public string StudentID { get; set; }
}
public class DriverRecord : Record
{
public string DLNumber { get; set; }
}
public class client
{
public static void Main()
{
StudentRecord st = StudentRecord.Default;
DriverRecord dr = DriverRecord.Default;
}
}
}
I want the default property or method to initialize all the class level properties to their defaults and I don’t want to repeat the implementation for each class. I just want to write on Record (base ) class . Can you provide some suggestions on this?
What you’re looking for is exactly what constructors are for. A constructor can call an inherited base constructor, so you need to do the base initialisation in only one place. Sometimes the basic functionality really does what you need :)
public class Record
{
public int ID { get; set; }
public Record()
{
// ... do general initialisation here ...
}
}
public class StudentRecord : Record
{
public string StudentID { get; set; }
public StudentRecord()
: base() // This calls the inherited Record constructor,
// so it does all the general initialisation
{
// ... do initialisations specific to StudentRecord here ...
}
}
public class client
{
public static void Main()
{
// This calls the constructor for StudentRecord, which
// in turn calls the constructor for Record.
StudentRecord st = new StudentRecord();
}
}
The Record class can only set the properties which are inherited by StudentRecord and DriverRecord. If you want to set class-specific properties to their default values you have to override the method (I would make a method) and do something like this (for StudentRecord ):
public void override Initialize()
{
base.Reset();
this.StudentId = 0;
}
HTH
You don't have any "class level properties", i.e. static properties, in your code sample. The properties you do have (the instance properties) are already initialized to their defaults -- 0 for integers, null for references, etc.
If you want to define your own defaults -- perhaps ID should default to -1 until you save, and the strings should default to "" -- then that's exactly what constructors are for:
public class Record
{
public Record() { ID = -1; }
public int ID { get; set; }
}
public class StudentRecord : Record
{
public StudentRecord() { StudentID = ""; }
public string StudentID { get; set; }
}
// etc.
If you want something different from either of those, you'll have to explain what you're looking for.
I think Null Object Pattern is what you need.

Categories

Resources