response class with generic <T> - c#

Sorry if this has been asked before, but I can't find it and I'm not exactly sure what to search on.
I've got a generic response class like this:
public class ResponseModel<T>
{
public T Data { get; set; }
public Exception Ex { get; set; }
public string Message { get; set; }
public bool Success { get; set; }
}
I'd like to do something like the code below so that I can simply pass the errors up the stack by doing a return retVal.Set<T>(responseModelObject);
public ResponseModel<T> Set<T>(ResponseModel<T> rm)
{
Ex = rm.Ex;
Message = rm.Message;
return this;
}
This works fine if the T class is identical between retVal and responseModelObject, but won't compile if they don't match.
Is there a way to do this or am I just sol?

You may create an interface
public interface IResponseModel
{
Exception Ex { get; set; }
string Message { get; set; }
bool Success { get; set; }
}
public class ResponseModel<T> : IResponseModel
{
public T Data { get; set; }
public Exception Ex { get; set; }
public string Message { get; set; }
public bool Success { get; set; }
}
Then the method will look like
public ResponseModel<T> Set(IResponseModel rm)
{
Ex = rm.Ex;
Message = rm.Message;
return this;
}
Also interface will allow you to create collections of IResponseModel which may conrain generics of different types. It maybe also useful with async operations like Task<IResponseModel>, etc.

You could try to declare method as:
public ResponseModel<T> Set<TOther>(ResponseModel<TOther> rm)
{
Ex = rm.Ex;
Message = rm.Message;
return this;
}
Sample usage:
ResponseModel<int> a = new ResponseModel<int>();
ResponseModel<string> b = new ResponseModel<string>();
b.Set(a); // It compiles

Is this working ?
public ResponseModel<T,S> Set<S>(ResponseModel<T> rm)
{
Ex = rm.Ex;
Message = rm.Message;
return this;
}

Related

Pattern for exposing non generic and generic Class

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>

How to combine the common code to create a generic method?

I have below classes with which I generate a request object and serialize the response to get a JSON string. The definition of classes are as follows
PortfolioResponse & StocksInfo classes are for mentioning purpose as they contain a lot many fields which I would not be able to write here.
[DataContract]
public class BaseInfoRequest
{
[DataMember]
public string Token { get; set; }
}
[DataContract]
public class StocksInfoRequest : BaseInfoRequest
{
[DataMember]
public string SomeKey { get; set; }
}
[DataContract]
public class PortfolioInfoRequest : BaseInfoRequest
{
[DataMember]
public string PortfolioId { get; set; }
[DataMember]
public string SomeKey { get; set; }
}
[DataContract]
public class StocksInfoResponse
{
[DataMember(Name = "success")]
public bool Success { get; set; }
[DataMember(Name = "message")]
public string Message { get; set; }
[DataMember(Name = "stocks")]
public StocksInfo StocksInfo { get; set; }
[DataMember(Name = "pfolio")]
public PortfolioResponse PortfolioInfo { get; set; }
}
public class PortfolioResponse
{
}
public class StocksInfo
{
}
Now, to get the data from different other classes and services in project I use below two methods in let's say class Sample
private string GetsStocksInformation(StocksInfoRequest request)
{
var response = new StocksInfoResponse();
if (ValidateRequestToken(request) || string.IsNullOrWhiteSpace(request.SomeKey))
{
response.Message =
GetsResponse().ErrorMessage;
return JsonConvert.SerializeObject(response);
}
response.StocksInfo = GetsStocksInfo(request);
response.Success = true;
return JsonConvert.SerializeObject(response);
}
private string GetsPortfolioInformation(PortfolioInfoRequest request)
{
var response = new StocksInfoResponse();
if (!ValidateRequestToken(request) || string.IsNullOrWhiteSpace(request.SomeKey) ||
string.IsNullOrWhiteSpace(request.PortfolioId))
{
response.Message =
GetsResponse().ErrorMessage;
return JsonConvert.SerializeObject(response);
}
response.PortfolioInfo = GetsPortfolioInfo(request.SomeKey, request.PortfolioId);
response.Success = true;
return JsonConvert.SerializeObject(response);
}
Now, if you look closely enough both the methods are almost same except condition
if (ValidateRequestToken(request) || string.IsNullOrWhiteSpace(request.SomeKey)) &&
response.StocksInfo = GetsStocksInfo(request);
Apart from above two, both the methods do more or less same things. The definition of ValidateRequestToken is below
private bool ValidateRequestToken(BaseInfoRequest request)
{
return true;
}
How do I combine both methods to create a generic method ?

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.

How to define a class property with type T

How can I have a property which can accept object of any type (of class)... something like this?
public class HttpConnectorRequest
{
public int Id { get; set; }
public T RequestObject { get; set; } where T: class
public string ResponseData { get; set; }
public Exception Exception { get; set; }
}
I am trying to acheive an alternative for something like this:
public class HttpConnectorRequest
{
public int Id { get; set; }
public ClassA ClassARequestObject { get; set; }
public ClassB ClassBRequestObject { get; set; }
public ClassC ClassCRequestObject { get; set; }
public string ResponseData { get; set; }
public Exception Exception { get; set; }
}
That's fine - you just need to make it generic:
public class HttpConnectorRequest<T> where T: class
{
public int Id { get; set; }
public T RequestObject { get; set; }
public string ResponseData { get; set; }
public Exception Exception { get; set; }
}
Then you'd write something like:
var request = new HttpConnectorRequest<string>();
request.RequestObject = "Hello!";
Generics is a big topic - MSDN is probably a reasonable starting point, although I suspect you'll want to read about it in a tutorial or book at some point. (While my own book, C# in Depth, obviously covers generics, plenty of others do too :)
Note that this makes the whole type generic. If you want to make just a single property generic, you're out of luck... although you could make a method generic:
public class HttpConnectorRequest
{
// Other members elided
public void SetRequestObject<T>(T value) where T : class
{
...
}
public T GetRequestObject<T>() where T : class
{
...
}
}
Quite what this would do is up to you - bear in mind that someone could write:
var request = new HttpConnectorRequest();
request.SetRequestObject<string>("Hello");
var button = request.GetRequestObject<Button>();

Categories

Resources