Pattern for exposing non generic and generic Class - c#

I have implemented a common operation result for my methods and it look like this
public class OperResult
{
public string ErrorCode { get; private set; }
public string Message { get; private set; }
public object Data { get; private set; }
public bool Ok { get; private set; }
public string IncidentNumber { get; set; }
public static OperResult Success(Object data = null)
{
return new OperResult(data);
}
}
And the same operation result using generics
public class OperResult<T>
{
public string ErrorCode { get; private set; }
public string Message { get; private set; }
public T Data { get; private set; }
public bool Ok { get; private set; }
public string IncidentNumber { get; private set; }
public static OperResult<T> Success(T data = null)
{
return new OperResult<T>(data);
}
}
Is there any way to combine these two implementations and at the same time provide both Generic and non Generic version of this class?
Edit add more info about the type usage:
I want to easily create functions that return this type, for example i want to been able to create the following functions:
OperResult MakeAction()
OperResult<int> GetCount()
If I use inheritance OperResult:OperResult<Object> then OperResult.Suceess() will produce OperResult<Object> and the following will generate a compilation error:
OperResult MakeAction(){
return OperResult.Suceess(); //Cannot convert OperResult<Object> to OperResult
}
GitHub link to OperResult

As already mentioned in the comments, the non generic appears to be a OperResult<object>.
Originally went down that route but it proved to not suit the desired use case.
Switched it around to having the generic derive from the non generic and provide a new Data property.
public class OperResult {
protected OperResult(object data) {
this.Data = data;
}
public string ErrorCode { get; protected set; }
public string Message { get; protected set; }
public object Data { get; protected set; }
public bool Ok { get; protected set; }
public string IncidentNumber { get; protected set; }
public static OperResult Success(object data = null) {
return new OperResult(data ?? new object());
}
public static OperResult<T> Success<T>(T data) {
return new OperResult<T>(data);
}
}
public class OperResult<T> : OperResult {
public OperResult(T data)
: base(data) {
}
public new T Data { get; protected set; }
}
this allows the following syntax
int data = 10;
var result = OperResult.Success(data);
//result is OperResult<int>

Related

How to access a property in another class?

I am working with a WPF .Net Core 3 project.
In my UnbalancedViewModel I need to access an ID from another class (TestRunDto.cs).
UnbalancedViewModel
public class UnbalancedViewModel : ViewModelBase, IUnbalancedViewModel
{
private TestRunApi _testRunApi;
public UnbalancedViewModel(TestRunApi testRunApi, INotificationManager notifications)
{
_testRunApi = testRunApi;
}
private void StartTestRunJobExecuted(object obj)
{
_testRunApi.StartTestRun(1); ////I need the Id from TestRunDto (TestRunDto.Id)
}
}
TestRunApi
public async Task<TestRunLiveValueDto> GetTestRunLiveValue(int jobRunId)
{
await using var dbContext = new AldebaDbContext(_connectionString);
return await TestRunInteractor.GetTestRunLiveValue(jobRunId, dbContext);
}
public async Task StartTestRun(int testRunId)
{
await using var dbContext = new AldebaDbContext(_connectionString);
await TestRunInteractor.StartTestRun(dbContext, testRunId);
}
TestRunLiveValueDto
public class TestRunLiveValueDto
{
public TestRunDto TestRun { get; }
public bool ShowInstantaneousValue { get; set; }
public bool EnableStart { get; set; }
public bool EnableStop { get; set; }
public bool EnableMeasure { get; set; }
public int RecipeRpm { get; }
public string ActualRecipeName { get; }
public int DefaultSetOfPlaneId { get; }
public ICollection<BalancePlaneDto> ListBalancePlane { get; }
public ICollection<SetOfPlaneDto> ListSetOfPlane { get; }
public ICollection<SensorVibrationDto> SensorVibrations { get; set; }
public ICollection<EstimationDto> InstantaneousValues { get; set; }
public ICollection<EstimationDto> EstimationsValues { get; set; }
private TestRunLiveValueDto(TestRunDto testRun, bool enableStart, bool enableStop, int recipeRpm, ICollection<SensorVibrationDto> sensorVibrations)
{
EnableStart = enableStart;
EnableStop = enableStop;
TestRun = testRun;
RecipeRpm = recipeRpm;
SensorVibrations = sensorVibrations;
}
public static TestRunLiveValueDto Create(TestRunDto testRun, bool enableStart, bool enableStop, int recipeRpm, ICollection<SensorVibrationDto> sensorVibrations)
=> new TestRunLiveValueDto(testRun, enableStart, enableStop, recipeRpm, sensorVibrations);
}
TestRunDto
public class TestRunDto
{
public int Id { get; set; }
public int JobRunId { get; set; }
public string Name { get; set; }
public int TestRunNumber { get; set; }
public RunState State { get; set; }
public ICollection<BalancePlaneDto> BalancePlanes { get; set; } // Todo remove
private TestRunDto(int id, int jobRunId, RunState state, string name, int testRunNumber)
{
Id = id;
JobRunId = jobRunId;
Name = name;
TestRunNumber = testRunNumber;
State = state;
}
public static TestRunDto Create(int id, int jobRunId, RunState state, string name, int testRunNumber)
=> new TestRunDto(id, jobRunId, state, name, testRunNumber);
}
I have been trying to understand this, but I can not get a hold of the proper method to do this. Do I first declare a new TestRunDto class in my viewmodel or am I supposed to access it some other way?
You need to ensure class A has a reference to an instance of class B to access the properties, for example one way of doing this is to pass class A to B in a method where you can manipulate or access properties.
public class FooA
{
public string PropertyA { get; set; }
}
public class FooB
{
public string PropertyB { get; set; }
public void CanAccessFooA(FooA a)
{
a.PropertyA = "See, I can access this here";
}
}
Another is to pass class A to B in the constructor (known as dependency-injection)
public class FooB
{
FooA _a;
public FooB(FooA a)
{
// Pass instance of FooA to constructor
// (inject dependency) and store as a member variable
this._a = a;
}
public string PropertB { get; set; }
public void CanAccessFooA()
{
if (this._a != null)
this._a.PropertyA = "See, I can access this here";
}
}
Exactly how to structure your code is up to you, but the principle remains the same: Class B can only access Class A if it has a reference to an instance of it.
Look into 'Dependency Injection' as there are many techniques to achieve this.
Edit
One such technique might be abstracting the code to provide the ID to both, like so
public class IdProvider
{
public int Id { get; set; }
}
public class FooA
{
private int _id;
public FooA(IdProvider idProvider)
{
_id = idProvider.Id;
}
}
public class FooB
{
private int _id;
public FooB(IdProvider idProvider)
{
_id = idProvider.Id;
}
}
Now both classes have the same ID;
StartTestRun takes the tesRunId as it's parameter.
public async Task StartTestRun(int testRunId)
{
I think you need to call StartTestRunJobExecuted with this testRunId.
You will to change
private void StartTestRunJobExecuted(object obj)
to
private void StartTestRunJobExecuted(int testRunIdn)
{
_testRunApi.StartTestRun(testRunId); ////I need the Id from TestRunDto (TestRunDto.Id)
}
(This based on me guessing).

How do I create a generic List using abstract class?

I have a Json class "GetAllDevices()". My JSON response consists of an Array/List of objects, where each object has the below common properties.
public class GetAllDevices
{
[JsonProperty("_id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("actions")]
public Action[] Actions { get; set; }
public class Action
{
public string _id { get; set; }
public Action_Def action_def { get; set; }
}
public class Action_Def
{
public string _id { get; set; }
public string name { get; set; }
}
}
I want to create 2 generic lists containing all the above properties based on its "type".
lstfoo1 List contains all the properties(_id, name type and actions) where type="foo1". Similarly, lstfoo2 is a List which contains the above properties where type="foo2".
What I have done so far:
string strJson=getJSON();
Foo1 lstfoo1=new Foo1();
Foo2 lstfoo2=new Foo2();
List<Foo1> foo1list= lstfoo1.GetDeviceData(strJson);
List<Foo2> foo2list = lstfoo2.GetDeviceData(strJson);
public class AllFoo1: GetAllDevices
{
}
public class AllFoo2: GetAllDevices
{
}
public abstract class HomeDevices<T>
{
public string type { get; set; }
public string _id { get; set; }
public List<AllFoo1> lstfoo1{ get; set; }
public List<AllFoo2> lstfoo2{ get; set; }
public abstract List<T> GetDeviceData(string jsonResult);
}
public class Foo1: HomeDevices<AllFoo1>
{
public Foo1()
{
type = "foo1";
}
public override List<AllFoo1> GetDeviceData(string jsonResult)
{
var lst =Newtonsoft.Json.JsonConvert.DeserializeObject<List<AllFoo1>>(jsonResult);
var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
return lst1;
}
}
public class Foo2: HomeDevices<AllFoo2>
{
public Foo2()
{
type = "foo2";
}
public override List<AllFoo2> GetDeviceData(string jsonResult)
{
var lst = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AllFoo2>>(jsonResult);
var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
return lst1;
}
}
My question is, is there an easier way to do this using abstract classes? Can I directly convert my "GetAllDevices" class into an abstract class and inherit it and deserialize into it and create a generic list?
This should help, if I understand your problem correctly. Let me know if you have questions or it doesn't work as you need. I put this together really quickly without testing.
The way the Type property is defined could be improved but I left it as you had it.
public class MyApplication
{
public void DoWork()
{
string json = getJSON();
DeviceTypeOne foo1 = new DeviceTypeOne();
DeviceTypeTwo foo2 = new DeviceTypeTwo();
IList<DeviceTypeOne> foo1Results = foo1.GetDeviceData(json); // calls GetDeviceData extension method
IList<DeviceTypeTwo> foo2Results = foo2.GetDeviceData(json); // calls GetDeviceData extension method
}
}
// implemented GetDeviceData as extension method of DeviceBase, instead of the abstract method within DeviceBase,
// it's slightly cleaner than the abstract method
public static class DeviceExtensions
{
public static IList<T> GetDeviceData<T>(this T device, string jsonResult) where T : DeviceBase
{
IEnumerable<T> deviceDataList = JsonConvert.DeserializeObject<IEnumerable<T>>(jsonResult);
IEnumerable<T> resultList = deviceDataList.Where(x => x.Type.Equals(typeof(T).Name));
return resultList.ToList();
}
}
// abstract base class only used to house common properties and control Type assignment
public abstract class DeviceBase : IDeviceData
{
protected DeviceBase(string type)
{
if(string.IsNullOrEmpty(type)) { throw new ArgumentNullException(nameof(type));}
Type = type; // type's value can only be set by classes that inherit and must be set at construction time
}
[JsonProperty("_id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("type")]
public string Type { get; private set;}
[JsonProperty("actions")]
public DeviceAction[] Actions { get; set; }
}
public class DeviceTypeOne : DeviceBase
{
public DeviceTypeOne() : base(nameof(DeviceTypeOne))
{
}
}
public class DeviceTypeTwo : DeviceBase
{
public DeviceTypeTwo() : base(nameof(DeviceTypeTwo))
{
}
}
// implemented GetAllDevices class as IDeviceData interface
public interface IDeviceData
{
string Id { get; set; }
string Name { get; set; }
string Type { get; }
DeviceAction[] Actions { get; set; }
}
// renamed and relocated class Action to DeviceAction
public class DeviceAction
{
public string Id { get; set; }
public DeviceActionDefinition DeviceActionDefinition { get; set; }
}
// renamed and relocated Action_Def to DeviceActionDefinition
public class DeviceActionDefinition
{
public string Id { get; set; }
public string Name { get; set; }
}
It should be simple enough to move the implementation of method GetDeviceData() to the base class.
For this to work, you will need to add a constraint on T so the compiler knows a bit more about the base type. You will also need to implement a constructor to populate the concrete type's type string you use around. This is a necessary measure to ensure the value is always populated as it is used for comparison in the method in question:
public abstract class HomeDevices<T> where T: GetAllDevices
{
public HomeDevices(string concreteType)
{
type = concreteType;
}
public string type { get; set; }
public string _id { get; set; }
public List<AllFoo1> lstfoo1 { get; set; }
public List<AllFoo2> lstfoo2 { get; set; }
//This method is now generic and works for both.
public List<T> GetDeviceData(string jsonResult)
{
var lst = Newtonsoft.Json.JsonConvert.DeserializeObject<List<T>>(jsonResult);
var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
return lst1;
}
}
I hope that helps.

Retrieving generic data without knowing the List<Type> to be returned, is that possible?

I dont know if the question is correct but what I need to do is to received the correct entity from the messagetoprocess repository method with the corresponding data, how can I do that in this scenario? (code below)
Im using AutoMapper.
I know that I can create a MessageEntity and eliminate the Interface and put all properties together in it but that is exactly what Im trying not to do.
Here is what I've got:
Interface:
public interface IMessage
{
string MessageFrom { get; set; }
string MessageTo { get; set; }
{
Implementer Entities
public class EmailMessageEntity : IMessage
{
public bool IsMessageBodyHtml { get; set; }
}
public class SmsMessageEntity : IMessage
{
public bool IsMmsMessage { get; set; }
}
Models:
public class EmailMessage
{
public string MessageFrom { get; set; }
public string MessageTo { get; set; }
public bool IsMessageBodyHtml { get; set; }
}
public class SMSMessage
{
public string MessageFrom { get; set; }
public string MessageTo { get; set; }
public bool IsMmsMessage { get; set; }
}
Repositry:
public static List<*****Entity problem*****> RetrieveMessageToProcess()
{
var commandSettings = new CommandSettings
{
CommandText = #"[Schema].[RetrieveMessageToProcess]",
CommandType = CommandType.StoredProcedure
};
return new MsSqlProviderBase(DbConnectionString, commandSettings).ExecuteQuery<*****Entity problem*****>();
}
Using it:
//code excerpt
var messagesToProcess = Db.RetrieveMessageToProcess(); //repository
if (messagesToProcess == null) return;
// Process Message(s)
foreach (var messageEntity in messagesToProcess)
{
if (Email) // this is just the verification example not the actual statement and not a variable
{
Mapper.CreateMap<EmailMessageEntity, EmailMessage>();
var emailMessage = Mapper.Map<EmailMessage>(messageEntity);
}
else if (SMS)
{
Mapper.CreateMap<SMSMessageEntity, SMSMessage>();
var smsMessage = Mapper.Map<SmsMessage>(messageEntity);
}
}
Could you consider having a MessageType member on your IMessage interface instead of the two IsXXX properties ?
You could return an enum, or whatever other value you deem appropriate, and use that in your if(EMAIL) statement.

Trying to work out these interfaces

I'm trying to create some interfaces. The IReportSection object will have one string and a collection of items, which could be different depending on what we're working with. Do I need to make it generic?
The IReport will have one string and a collection of IReportSection.
Here's how I'm trying to define it now.
public interface IReport
{
string ReportName { get; set; }
ICollection<IReportSection> ReportSections { get; }
}
public interface IReportSection
{
string ReportSectionName { get; set; }
ICollection ReportItems { get; }
}
public abstract class ReportSectionBase : IReportSection
{
public string ReportSectionName { get; set; }
public ICollection ReportItems { get; set; }
}
And my models:
pulic class ProjectSubmissionViewModel
{
public int ProjectSubmissionId { get; set; }
public string SubmissionTitle { get; set; }
}
pulic class AffiliateViewModel
{
public int AffiliateId { get; set; }
public string AffiliateName { get; set; }
}
This is how I'm trying to use it in code:
public class ChapterAffiliates : ReportSectionBase
{
public string ReportSectionName { get { return "Chapter Affiliates"; } }
public ICollection<AffiliateViewModel> ReportItems { get; set; }
}
public class ChapterTitles : ReportSectionBase
{
public string ReportSectionName { get { return "Chapter Titles"; } }
public ICollection<ProjectSubmissionViewModel> ReportItems { get; set; }
}
public class SubmissionListViewModel : IReport
{
public ICollection<ProjectSubmissionViewModel> Submissions { get; set; }
public ICollection<AffiliateViewModel> Affiliates{ get; set; }
public string ReportName { get; set; }
public ICollection<IReportSection> ReportSections
{
get
{
var affiliateSection = new ChapterAffiliates
{
ReportItems = Affiliates
};
var titleSection = new ChapterTitles
{
ReportItems = Submissions.Where(s => s.SubmissionTitle.Contains("SomePhrase")).ToList()
};
var sections = new List<IReportSection> { {subSection}, {titleSection} };
return sections;
}
}
}
I'm not sure how to best define this. I'm pretty sure I've done it before, but it's not coming to me.
Are the type parameters for TRType all the same within a certain report? E.g. will you have report sections with different report types in them?
If all types within a report are the same, the solution is relatively simple:
public interface IReport<T> { ... }
If this is not the case - you'll have to do something different, e.g:
public interface IReportSection
{
string ReportSectionName { get; }
ICollection ReportItems { get; }
}
public abstract class ReportSectionBase<TRType> : IReportSection {
...
}
This allows you to put different underlying types in the ReportSections collection related to the report. You'll have to do some more work to get the exact information that you need out of each report section.

Access Protected Members in a Subclass

Im a little stuck and after some searching i turn to you:
class StatusResponse
{
protected int _statusCode { get; set; }
protected string _statusMessage { get; set; }
public StatusResponse(string Response)
{
if (!String.IsNullOrEmpty(Response))
{
this._statusCode = int.Parse((Response.Split(' '))[0].Trim());
this._statusMessage = Response;
}
}
}
class GroupStatusResponse : StatusResponse
{
public int Count { get; private set; }
public int FirstArticle { get; private set; }
public int LastArticle { get; private set; }
public string Newsgroup { get; private set; }
public GroupStatusResponse(string Response) : base(Response)
{
string[] splitResponse = Response.Split(' ');
this.Count = int.Parse(splitResponse[1].Trim());
this.FirstArticle = int.Parse(splitResponse[2].Trim());
this.LastArticle = int.Parse(splitResponse[3].Trim());
this.Newsgroup = splitResponse[4].Trim();
}
Why cant i do this:
GroupStatusResponse resp = new GroupStatusResponse("211 1234 3000234 3002322 misc.test");
Console.Writeline(resp._statusCode);
using
Console.Writeline(resp._statusCode);
from outside the derived class is public, and not protected use.
However, you could add something like:
class GroupStatusResponse : StatusResponse
{
public int GetStatusCode()
{
return _statusCode;
}
}
which is completely valid use.
Moreover, if the scenario is that _statusCode should be allowed to read by anyone, but only the base class should be able to set it, you could change its definition to:
public string _statusMessage { get; private set; }
It's because _statusCode is protected. This means the field is inaccessible outside of the class.

Categories

Resources