I have a three classes
public class A<T>
{
public bool Success {get; set;}
public string Reason {get; set;}
public T Data {get; set;}
}
public class B
{
public string Token {get; set;}
}
public class C
{
public int SomeInt {get; set;}
public string SomeString {get; set;}
public double SomeDouble {get; set;}
}
I call my web service and pass in A or A to deserialise into like this
async Task<T> MyTask<T>(...) (where T is A<B> or A<C>)
The service works fine and returns some JSON which if I try and to deserialise into a var, I'm getting nothing deserialised
To deserialise, I'm using
var foo = JsonConvert.DeserializeObject<T>(response.Content);
Is there a limitation to how I can deserialise the object so I can only use a base class rather than this form of class?
Yes, you can not just pass A because A is not base class, it is generic class and does not exists on its own.
C# generates generic classes during compile time, which means if you use A<B> in your code, C# will generate something like:
public class generated_A_B
{
public bool Success { get; set; }
public string Reason { get; set; }
public B Data { get; set; }
}
Nothing will be generated for A<C>, if not explicitly used. Reason is obvious, if you generate classes for every single combination of the A, you will bloat your code.
In your current situation it is better to just call them explicitly
void Main()
{
CallAB();
CallAC();
}
A<B> CallAB()
{
return ServiceCall<A<B>>("/api/ab");
}
A<C> CallAC()
{
return ServiceCall<A<C>>("/api/ac");
}
If you really want to get "generic" A, you should make A an actual base class and have your API to return the type of Data. In my example I just use Name of the type, but you probably should use FullName that includes namespace, to avoid name conflicts.
void Main()
{
var json = #"
{
""success"": true,
""reason"": ""All good"",
""type"": ""B"",
""data"": {
""token"": ""1234-5678""
}
}";
var foo = JsonConvert.DeserializeObject<A>(json);
var type = Assembly.GetExecutingAssembly().GetTypes().Where(i => i.IsClass && i.Name == foo.Type).FirstOrDefault();
if (type == null)
{
throw new InvalidOperationException(string.Format("Type {0} not found", foo.Type));
}
var data = foo.Data.ToObject(type);
}
public class A
{
public bool Success { get; set; }
public string Reason { get; set; }
public string Type { get; set; }
public JToken Data { get; set; }
}
public class B
{
public string Token { get; set; }
}
I would recommend either to go for the easy solution: create an intermediate merged your classes B and C, to something like
public class BC
{
public string Token { get; set; }
public int SomeInt { get; set; }
public string SomeString { get; set; }
public double SomeDouble { get; set; }
public bool IsB => !String.IsNullOrEmpty(Token);
public B ToB() => new B() { Token = Token };
public C ToC() => new C() { SomeInt = SomeInt, SomeString = SomeString, SomeDouble = SomeDouble };
}
Then you can call your service, and convert BC either to B or C:
async Task<A<BC>> MyTask<A<BC>>(...)
var abc = await MyTask(...);
if(abc.Data.IsB)
{
var resB = abc.data.ToB();
}
else
{
var resC = abc.data.ToC();
}
Or go to the more complicated solution, with some JsonConverter as explained in this answer:
how to implement custom jsonconverter in json net to deserialize a list of base
Related
I have the following construction of classes, here simplified as child classes of a 'mother' class called DataClass, which also contains one simple method:
public class DataClass
{
public int num { get; set; }
public string code { get; set; }
public PartClass part { get; set; }
public MemberClass member { get; set; }
public int Count()
{
Type t = typeof(DataClass);
return typeof(DataClass).GetProperties().Length;
}
}
public class PartClass
{
public int seriesNum { get; set; }
public string seriesCode { get; set; }
}
public class MemberClass
{
public int versionNum { get; set; }
public SideClass side { get; set; }
}
public class SideClass
{
public string firstDetail { get; set; }
public string secondDetail { get; set; }
public bool include { get; set; }
}
The issue is, I want to refactor the method so that it can give me an accurate counting of all properties found, including the ones in nested or child classes. In the above example, it only counts properties of DataClass, while I wanted it to return 2 for DataClass + 2 for PartClass + 1 for MemberClass + 3 for SideClass, sums up to 8 properties you may set through DataClass.
Can someone help me with this?
You can introduce interface with Count() method
public interface ICountable
{
int Count();
}
And use this interface to mark all types, which properties are participating in Count() calculation.
You can see the generic abstract class to implement this interface below. Generic T parameter is type whose properties need to be calculated. You implement a calculation logic only once and inherit this class where needed. You also go through all of properties, implementing ICountable, to calculate them as well (some kind of recursion)
public abstract class Countable<T> : ICountable
{
public int Count()
{
Type t = typeof(T);
var properties = t.GetProperties();
var countable = properties.Select(p => p.PropertyType).Where(p => typeof(ICountable).IsAssignableFrom(p));
var sum = countable.Sum(c => c.GetProperties().Length);
return properties.Length + sum;
}
}
and inherit it in your classes
public class DataClass : Countable<DataClass>
{
...
}
public class PartClass : Countable<PartClass>
{
...
}
public class MemberClass : Countable<MemberClass>
{
...
}
public class SideClass : Countable<SideClass>
{
...
}
And this is for the test
var dataClass = new DataClass();
var count = dataClass.Count();
It returns 8 as expected
In C#, is it possible to read a class tree path in a string and access programmatically a value, given an instance of that class ?
For example:
public class LogGeometricModel
{
public double SmallEndDiameter { get; set; }
public double LargeEndDiameter { get; set; }
public class Log
{
public Guid Id { get; set; }
public LogGeometricModel GeometricModel { get; set; }
}
public class Solution
{
public DateTime TimeStamp { get; set; }
public double Price { get; set; }
public Log RotatedLog { get; set; }
}
The strings could be something like this (a path in the class tree):
SmallEndDiameter = "Solution/RotatedLog/GeometricModel/SmallEndDiameter"
LargeEndDiameter = "Solution/RotatedLog/GeometricModel/LargeEndDiameter"
Price = "Solution/Price"
Id = "Solution/Log/Id"
By reading those strings, I would like to access the actual values of SmallEndDiameter, LargeEndDiameter, Price and Id.
Absolutely possible yes.
public static object GetValue(object instance, string path)
{
object currentObject = instance;
foreach (string propertyName in path.Split('/'))
{
currentObject = currentObject
.GetType()
.GetProperty(propertyName)
.GetValue(currentObject, null);
}
return currentObject;
}
You don't need to include 'Solution' in the string. This obviously lacks error handling, which if you are parsing a string like this, you will want.
Original Question
So I have this 3 objects...
public class obj1
{
public int Id { get; set; }
public string Name { get; set; }
}
public class obj2
{
public int AccNum { get; set; }
public string Name { get; set; }
}
public class obj3
{
public string Email { get; set; }
public string Phone { get; set; }
}
... and one method that is supposed to receive one of them, after evaluating the object type the program should decide which function to call.
I've tried with generics but it doesn't work as I expected. So far this is what I've got...
public class NotificationHelper: INotificationHelper
{
public bool SendNotification<TNotInfo>(TNotInfo obj) where TNotInfo : class
{
if (contract.GetType() == typeof (obj1))
{
var sender = new SendSMS();
return sender.Send(obj);
}
if (contract.GetType() == typeof(obj2))
{
var sender = new SendPush();
return sender.Send(obj);
}
else
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
}
but I get the error "Cannot convert from TNotInfo to Models.obj1". Is there any way to overcome this issue? Or I have to change my logic?
Appreciate any help, thanks in advance.
*Edit
using System;
namespace EmailNotifications
{
public interface IEmailNotification
{
void SendEmailNotification();
}
public class EmailNotificationA : IEmailNotification
{
public void SendEmailNotification(Contract1 a)
{
Console.WriteLine($"Sending EmailNotificationA ({a})");
}
}
public class EmailNotificationB : IEmailNotification
{
public void SendEmailNotification(Contract2 b)
{
Console.WriteLine($"Sending EmailNotificationB ({b})");
}
}
public class EmailNotificationC : IEmailNotification
{
public void SendEmailNotification(Contrac3 c)
{
Console.WriteLine($"Sending EmailNotificationC ({c})");
}
}
public class EmailNotificationService
{
private readonly IEmailNotification _emailNotification;
public EmailNotificationService(IEmailNotification emailNotification)
{
this._emailNotification = emailNotification;
}
public void ServiceHelper()
{
_emailNotification.SendEmailNotification();
}
}
}
Above solution is what I was trying to achieve, applying strategy design pattern. But I couldn't manage to make my interface method receive different objects, this is required because each notification has is own implementation. As visible at the none working example above, I have 3 different implementation of the same method all of them receiving different objects. Any idea of how to make this logic work?
This is the kind of thing that interfaces were designed to do. First, define a common interface:
public interface INotifier
{
bool Notify();
}
Second, implement it in your objX classes:
public class obj1 : INotifier
{
public int Id { get; set; }
public string Name { get; set; }
public bool Notify()
{
var sender = new SendSMS();
return sender.Send(this);
}
}
public class obj2 : INotifier
{
public int AccNum { get; set; }
public string Name { get; set; }
public bool Notify()
{
var sender = new SendPush();
return sender.Send(this);
}
}
public class obj3 : INotifier
{
public string Email { get; set; }
public string Phone { get; set; }
public bool Notify()
{
var sender = new SendEmail();
return sender.Send(this);
}
}
And finally, change your notification method to accept the interface type as the parameter:
public class NotificationHelper : INotificationHelper
{
public bool SendNotification(INotifier obj)
{
return obj.Notify();
}
}
Edit (2019):
I'm revisiting this answer as it seems to be getting a fair amount of visibility. OP has probably long since moved on, but for others that may stumble upon this answer, here's another solution.
I still believe that interfaces are the way to go. However, the interface suggested above is extremely generic and ultimately not terribly useful. It also runs into some DRY violations because, as Fabio said in a comment, if two objX classes implement notifications in the same way, this approach forces you to duplicate the code between them.
Instead of one global interface, instead have interfaces for each specific notification task, i.e. ISMSNotification, IPushNotification, IEmailNotification. You can then use the mixin pattern to give each interface instance a default implementation of the send method:
interface ISmsNotifier
{
int SmsId { get; }
string SmsName { get; }
}
static class ISmsNotifierExtensions
{
public static bool NotifySms(this ISmsNotifier obj)
{
var sender = new SendSMS();
return sender.Send(obj);
}
}
// ---------------------------------------------
interface IPushNotifier
{
int PushAccNum { get; }
string PushName { get; }
}
static class IPushNotifierExtensions
{
public static bool NotifyPush(this IPushNotifier obj)
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
// ---------------------------------------------
interface IEmailNotifier
{
string EmailAddress { get; }
string EmailPhone { get; }
}
static class IEmailNotifierExtensions
{
public static bool NotifyEmail(this IEmailNotifier obj)
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
You can then implement it in the objX classes like so:
public class obj1 : INotifier, ISmsNotifier
{
public int SmsId { get; set; }
public string SmsName { get; set; }
public bool Notify() => this.NotifySms();
}
public class obj2 : INotifier, IPushNotifier
{
public int PushAccNum { get; set; }
public string PushName { get; set; }
public bool Notify() => this.NotifyPush();
}
public class obj3 : INotifier, IEmailNotifier
{
public string EmailAddress { get; set; }
public string EmailPhone { get; set; }
public bool Notify() => this.NotifyEmail();
}
Notice that using this approach it's easy to not only support objects which use identical notification systems, you can also support objects with multiple notification systems:
public class obj4 : INotifier, IEmailNotifier, IPushNotifier
{
public int PushAccNum { get; set; }
public string PushName { get; set; }
public string EmailAddress { get; set; }
public string EmailPhone { get; set; }
public bool Notify() => this.NotifyEmail() && this.NotifyPush();
}
You might notice that this approach makes NotificationHelper obsolete since it's no longer necessary to pass the objects through a processing step to determine which notification system to process the object through. That is true, and maybe rightfully so, since the objects should be fully capable of deciding that for themselves (depending on your mentality approaching this problem). However, NotificationHelper may still have its uses, such as if you wanted to preprocess the information that's getting sent to the notification services, or if you wanted a common point of entry to help with mocking and testing.
C# 8 Note:
A proposed feature of C# 8 is the ability to give interfaces a default implementation of methods within the interface definition itself. When (if) that happens, you don't need to use the mixin pattern anymore and can directly define the default method implementations in the interfaces. The feature hasn't yet been finalized, but it might look something like this:
interface ISmsNotifier
{
int SmsId { get; }
string SmsName { get; }
public bool NotifySms()
{
var sender = new SendSMS();
return sender.Send(this);
}
}
// ---------------------------------------------
interface IPushNotifier
{
int PushAccNum { get; }
string PushName { get; }
public bool NotifyPush()
{
var sender = new SendEmail();
return sender.Send(this);
}
}
// ---------------------------------------------
interface IEmailNotifier
{
string EmailAddress { get; }
string EmailPhone { get; }
public bool NotifyEmail()
{
var sender = new SendEmail();
return sender.Send(this);
}
}
Another approach will be overload methods.
Because you have different logic based on the given type. And types have nothing in common (interface/abstract class).
public class NotificationHelper
{
public bool SendNotification(obj1 obj)
{
var sender = new SendSMS();
return sender.Send(obj);
}
public bool SendNotification(obj2 obj)
{
var sender = new SendPush();
return sender.Send(obj);
}
public bool SendNotification(obj3 obj)
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
Then using will be clear enough
var someObject = GetObjectFromSomeWhere();
var isSuccessful = SendNotification(someObject);
I would suggest creating a parent class from which these 3 inherit
public class ParentType { }
public class Obj1 : ParentType { ... }
The method would then just request the parent type, such as:
public bool SendNotification(ParentType obj) { ... }
I have two classes with some similar fields, some different, and a form that utilizes two different objects depending on what mode it's in (insert/edit).
Instead of using two different objects and if statements checking the form mode, I'd like to have one struct to be hydrated with either of the two objects fields so I can manipulate one object through the page life-cycle. Then separated the struct back to its respective object for insert/updating the DB.
Example of classes:
public partial class SomeClass
{
public Int32 B {get;set;}
public String C {get;set;}
public Boolean D {get;set;}
}
public class SomeOtherClass
{
public Int32 A {get;set;}
public Int32 B {get;set;}
public String C {get;set;}
}
Update with Solution Example:
public interface IInsertable
{
string SharedName { get; set; }
string SharedID { get; set; }
string editedFieldValue { get; set; }
long GetSuperSecreteInfo();
}
internal class InsertableImplementation : IInsertable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return -1;
}
}
public interface IUpdateable
{
string SharedName { get; set; }
string SharedID { get; set; }
string updatedFieldValue { get; set; }
Guid GenerateStevesMagicGuid();
}
internal class UpdateableImplementation : IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
public static class WonderTwinFactory
{
public static WonderTwins GenerateWonderTwin(IUpdateable updateable, IInsertable insertable)
{
var wt = new WonderTwins();
// who will win?
wt.SharedID = updateable.SharedID;
wt.SharedID = insertable.SharedID;
// you decide?
wt.SharedName = updateable.SharedName;
wt.editedFieldValue = "stuff";
return wt;
}
}
public class WonderTwins : IInsertable, IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return 1;
}
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
class Program
{
static void Main(string[] args)
{
IUpdateable updateable = new UpdateableImplementation();
IInsertable insertable = new InsertableImplementation();
WonderTwins dualImplementatin = WonderTwinFactory.GenerateWonderTwin(updateable, insertable);
IUpdateable newUpdateable = dualImplementatin as IUpdateable;
IInsertable newInsertable = dualImplementatin as IInsertable;
}
}
Have both classes implement an interface that defines the operations common to each, including both the fields that are shared (assuming the view needs to access them) and also a method to actually perform the operation that they represent (insert/edit).
Other way of doing such things is using C# dynamic object and assign properties directly. It may help to avoid any new type or interface and directly utilizing new dynamic object any time, as much as required.
var newObject = new {
objectOfClass1 = x.prop1,
objectOfClass2 = x.prop2
}
I am having a difficult time parsing a json response with C# asp.net. mostly with the array within array structure of this response. I have edited the post to reflect the json object. I think we can omit the deserialzation code.
{"Level1":
[
{
A:"some",
B:"more",
C:"stuff"
}
],"DataLevel":
[[
{ "AnotherLevel":
{
"File":"data"
},
"More":"stuff"
}
]]}
// C# code
public class JsonObject
{
public Level1[] level1 {get;set;}
public DataLevel[] datalevel {get;set;}
}
public class Level1
{
public string A {get;set;}
public string B {get;set;}
public string C {get;set;}
}
public class DataLevel
{
// ??
// Seems like this should be public AnotherLevel anotherlevel {get;set;}
public string More {get;set;}
}
Ok so looking at your data I would say your class definitions do not match the json you posted. Look closely at it. You have an object with 2 properties. One is an array of objects, the other is an array of object arrays. Below I have a different set of class definitions that should solve your problems.
public class OuterObject
{
public FirstArrayObject[];
public List<ObjInNestedArray[]>;
}
public class FirstArrayObject
{
public string A;
public string B;
public string C;
}
public class ObjInNestedArray
{
string property1;
AnotherLevel AnotherLevel;
}
public class AnotherLevelObj
{
string prop1;
}
OuterObject response = JsonConvert.DeserializeObject<OuterObject>(responseBodyAsString);
I don't know how good this is and didn't check if it is actually correct but you could try this website http://json2csharp.com/, but it might help you in some way!
This is the result I got when I used the json data you provided:
class Level1
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
}
public class RootObject
{
public List<Level1> Level1 { get; set; }
public List<List<>> DataLevel { get; set; }
}