I have a Report Interface which has a Run method.
There are different types of reports which implement this interface and each run their own kind of report, getting data from different tables.
Each report, using its own data context, gets data which then populates Business Objects with and at the moment they are returned as an array (I would like to be able to at least return something like a list but because you have to define the list type it makes it a bit more difficult).
Reflection is then used to find out the properties of the returned data.
I hope I have explained this well enough!
Is there a better way of doing this?
By request:
public interface IReport
{
int CustomerID { get; set; }
Array Run();
}
public class BasicReport : IReport
{
public int CustomerID { get; set; }
public virtual Array Run()
{
Array result = null;
using (BasicReportsDataContext brdc = new BasicReportsDataContext())
{
var queryResult = from j in brdc.Jobs
where j.CustomerID == CustomerID
select new JobRecord
{
JobNumber = j.JobNumber,
CustomerName = c.CustomerName
};
result = queryResult.ToArray();
}
}
}
The other class then does a foreach over the data, and uses reflection to find out the field names and values and puts that in an xml file.
As it stands everything works - I just can't help thinking there is a better way of doing it - that perhaps my limited understanding of C# doesn't allow me to see yet.
Personnally I would first ask myself if I Really need an interface. It would be the case if the classes implementing it are Really different by nature (not only by report kind).
If not, i.e all the implementing classes are basically "Reporters", then yes, there is a more convenient way to do this which is :
Writing a parent abstract Report
Having a virtual Run method and the CustomerID accessor
inheriting your "Reporter" classes from it
Related
Consider the following code:
public interface IIdentifiable<T>
{
T Id { get; set; }
}
public interface IViewModel
{
}
public class MyViewModel1 : IViewModel, IIdentifiable<int>
{
public string MyProperty { get; set; }
public int Id { get; set; }
}
public class MyViewModel2 : IViewModel, IIdentifiable<string>
{
public string MyProperty { get; set; }
public string Id { get; set; }
}
I also have class that operates with ViewModels:
public class Loader<T> where T: IViewModel
{
public void LoadData()
{
/*some important stuff here*/
if (typeof(IIdentifiable<??>).IsAssignableFrom(typeof(T)))
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<??>) ds).Id != ((IIdentifiable<??>) d).Id)).ToList();
} // ^---- and there the second ----^
/*some important stuff here too*/
}
}
Now, as you can see, viewmodels that I have might implement the IIdentifiable<> interface. I want to check that, and if it's true,
I want to make sure my data list does not contains any entry that are already present in my _dataSourse list.
So I have 2 questions:
I don't know what IIdentifiable<> has in its generic parentheses, it might be int, string or even GUID.
I tried typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) which is the correct syntax, yet it always returns false.
Is there a way to check whether T is IIdentifiable<> without knowing the exact generic type?
If there is an answer for the first question, I would also like to know how can I compare the Id fields without knowing their type.
I found this answer quite useful, yet it doesn't cover my
specific case.
I know that I probably can solve that problem if I make my Loader<T> class a generic for two types Loader<T,K>, where K would be the
type in IIdentifiable<>, yet I would like to know if there are other solutions.
P.S. In addition to my first question: I'm also curious why one can write something like this typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) if it returns false when the generic type of IIdentifiable<> is not specified?
Edit: I guess, in hindsight, I understand why I can't write the code this bluntly - because there's might be the collection ICollection<IViewModel> where the entries implement different types of IIdentifiable<> (or don't implement it at all), and the check like that would fail awkwardly. Yet maybe there is a way to do something like that with some restrictions, but without creating second generic parameter to my Loader?
Try add two methods to your Loader<T>:
public bool CanCast<TId>()
{
var identifiableT = typeof(IIdentifiable<>).MakeGenericType(typeof(TId));
return identifiableT.IsAssignableFrom(typeof(T));
}
public IEnumerable<IIdentifiable<TId>> Filter<TId>(IEnumerable<T> data)
{
return data.Where(d => _dataSource.All(
ds => !((IIdentifiable<TId>) ds).Id.Equals(((IIdentifiable<TId>) d).Id)));
}
Then in LoadData
if (CanCast<int>())
data = Filter<int>(data);
else if (CanCast<Guid>())
data = Filter<Guid>(data);
// and so om
Well, I would suggest you to always use a string for identification. You can convert int and guid to a string. And if you want to ensure proper type is used then you can prefix the string with type information.
However, I do think that the performance of you algorithm would be very poor as you wouls essentially loop 2 containers so it would be O(n * m).
Thus it would be best to either do appropriate SQL query if both sources are from the database or use a dictionary if you do it in code. Alternatively if data is properly sorted, you could find duplicates more efficiently.
By the way generics are quite limited in C#. Sometime using ˋFunc<>ˋ could help but even then you have to provide extra information to the algorithm.
We should address your question in two steps (because there really are two problems to solve here).
First, make following change to your interface IIdentifiable<T>
public interface IIdentifiable<T>
where T : IEquatable<T>
{
T Id { get; set; }
}
This will ensure that you can compare Id properties correctly.
Secondly, in your LoadData() method, change the if statement to
if (T is IIdentifiable<T>)
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<T) ds).Id != ((IIdentifiable<T) d).Id)).ToList();
}
I'm using Redis Cache using Stack Exchange library.
I used cloudStructure library to use Redis Dictionary and Redis List.
Problem is when I try to retrieve values and if that model has a null
value for one list property it is throwing me below exception -
Jil.DeserializationException : Error occurred building a deserializer
for TestMainClass: Expected a
parameterless constructor for
System.Collections.Generic.ICollection1[TestChildClass]
---- Jil.Common.ConstructionException : Expected a parameterless constructor for
System.Collections.Generic.ICollection1[TestChildClass]
public class TestMainClass
{
public TestMainClass();
public int Id { get; set; }
public virtual ICollection<TestChildClass> Mydata { get; set; }
public string Title { get; set; }
}
public class TestChildClass
{
public TestChildClass();
public int Id { get; set; }
public string Value { get; set; }
}
Redis code for retrieve value:
RedisDictionary<int, TestMainClass> dictionary =
new RedisDictionary<int, TestMainClass>("localhost", "mylocaldictionary");
var result = await dictionary.Get(121);
What If I could not able to convert ICollection < T > into List < T >?
It might be a nice feature if the serialization library detected interfaces like ICollection<T> and IList<T> and implemented them with the concrete List<T> during deserialization, but ultimately: every feature needs to be thought of, considered (impact), designed, implemented, tested, documented and supported. It may be that the library author feels this is a great idea and should be implemented; it might not be high on the author's list, but they'd be more than happy to take a pull request; or there might be good reasons not to implement it.
In the interim, as a general rule that will solve virtually every serialization problem you will ever encounter with any library:
the moment the library doesn't work perfectly with your domain model: stop serializing your domain model - use a DTO instead
By which, I mean: create a separate class or classes that are designed with the specific choice of serializer in mind. If it wants List<T>: then use List<T>. If it wants public fields: use public fields. If it wants the types to be marked [Serializable]: mark the types [Serializable]. If it wants all type names to start with SuperMagic: then start the type name with SuperMagic. As soon as you divorce the domain model from the serialization model, all the problems go away. In addition: you can support multiple serializers in parallel, without getting into the scenario that A needs X and doesn't work with Y; B needs Y and doesn't work with X.
All you then need to do is write a few lines of code to map between the two similar models (or use libraries that do exactly that, like AutoMapper).
I have a summary objects, who's responsibilities actually to combine a lot of things together and create a summary report, who later going to be serialized into the XML.
In this objects I have a lot of structures like this:
public class SummaryVisit : Visit, IMappable
{
public int SummaryId { get; set; }
public int PatientId { get; set; }
public int LocationId { get; set; }
public IMappable Patient
{
get
{
return new SummaryPatient(PatientBusinessService.FindPatient(this.PatientId));
}
}
public IMappable Location
{
get
{
return new SummaryLocation(LocationBusinessService.FindLocation(this.LocationId));
}
}
public IEnumerable<IMappable> Comments
{
get
{
return new SummaryComments(CommentBusinessService.FindComments(this.SummaryId, Location));
}
}
// ... can be a lot of these structures
// ... using different business services and summary objects
public IEnumerable<IMappable> Tasks
{
get
{
return new SummaryTasks(TaskBusinessService.FindTasks(this));
}
}
}
PatientBusinessService, LocationBusinessService etc. are statics.
And each of these SummaryPatient, SummaryLocation etc. have the same type of structure inside.
What is the best approach to refactor and unit test this?
Tried to replace static calls with calls via the interfaced proxies (or refactor statics to non-static classes & interfaces), but this class just got a lot of these interfaces as the constructor injection stuff and start to be super greedy. In addition, these interfaces have a one used method inside (if I going to create it just to this summary needs).
And as soon as this is a summary object, commonly this static services used just once for the whole structure to get appropriate properties for output.
You could change your tests to be more integrational (test more than one class at the time). You could try to modify your services to be more universal and be able to take data from different sources (like TestDataProvider and your current data provider).
Better solution I think is to modify classes you want to test:
Use strong typing for properties and gain all benefits. I think you should return more specific types instead of IMappable
It looks like some of your data is stored inside class (ids) some data is not (IMappable object references). I would refactor this to hold references to objects inside class:
private SummaryPatient _patient;
public SummaryPatient Patient
{
get
{
if (_patient == null)
_patient = new SummaryPatient(PatientBusinessService.FindPatient(this.PatientId));
return _patient;
}
}
Then you can assign your tests data in constructor or create static method CreateDummy(...) just for unit tests. This method then should use CreateDummy for child objects. You can use it in your unit tests.
I have a situation where I am querying a RESTful web-service (using .NET) that returns data as XML. I have written wrapper functions around the API so that instead of returning raw XML I return full .NET objects that mirror the structure of the XML. The XML can be quite complicated so these objects can be pretty large and heavily nested (ie. contain collections that in turn may house other collections etc.).
The REST API has an option to return a full result or a basic result. The basic result returns a small subset of the data that the full result does. Currently I am dealing with the two types of response by returning the same .NET object for both types of request - but in the basic request some of the properties are not populated. This is best shown by a (very oversimplified) example of the code:
public class PersonResponse
{
public string Name { get; set; }
public string Age { get; set; }
public IList<HistoryDetails> LifeHistory { get; set; }
}
public class PersonRequest
{
public PersonResponse GetBasicResponse()
{
return new PersonResponse()
{
Name = "John Doe",
Age = "50",
LifeHistory = null
};
}
public PersonResponse GetFullResponse()
{
return new PersonResponse()
{
Name = "John Doe",
Age = "50",
LifeHistory = PopulateHistoryUsingExpensiveXmlParsing()
};
}
}
As you can see the PersonRequest class has two methods that both return a PersonResponse object. However the GetBasicResponse method is a "lite" version - it doesn't populate all the properties (in the example it doesn't populate the LifeHistory collection as this is an 'expensive' operation). Note this is a very simplified version of what actually happens.
However, to me this has a definite smell to it (since the caller of the GetBasicResponse method needs to understand which properties will not be populated).
I was thinking a more OOP methodology would be to have two PersonResponse objects - a BasicPersonResponse object and a FullPersonResponse with the latter inheriting from the former. Something like:
public class BasicPersonResponse
{
public string Name { get; set; }
public string Age { get; set; }
}
public class FullPersonResponse : BasicPersonResponse
{
public IList<object> LifeHistory { get; set; }
}
public class PersonRequest
{
public BasicPersonResponse GetBasicResponse()
{
return new FullPersonResponse()
{
// ...
};
}
public FullPersonResponse GetFullResponse()
{
return new FullPersonResponse()
{
// ...
};
}
}
However, this still doesn't quite "feel" right - for reasons I'm not entirely sure of!
Is there a better design pattern to deal with this situation? I feel like I'm missing something more elegant? Thanks!
I my opinion you have describe a proxy pattern. See details here: Illustrated GOF Design Patterns in C#
I also have a nagging bad feeling about using inheritance to add on 'extra data', rather than adding/modifying behavior. The main advantage of this is that your methods can specify which level of detail they require in their argument types.
In this particular example, I would be inclined to use the first approach for the data transfer object (the Response object), but then immediately consume this data transfer object to create data model objects, the exact nature of which depends heavily on your specific application. The data transfer object should be internal (as the presence or absence of the data field is an implementation detail) and the public objects or interfaces should provide a view that's more suitable to the consuming code.
I have a web method which calls a method in the DAL to execute a procedure by id and returns an object of type MyData.
[WebMethod]
public MyData GetDataById(int id)
{
DAL myDAL = new DAL();
return myDAL.GetDataById(id);
}
The class MyData looks like the following
public class MyData
{
public string Name;
public Data[] DataItems;
}
and the class Data,
public class Data
{
public string key;
public string value;
}
Now this worked fine for until we wanted to return a bit of complex types.
For an example, a DataTable, or perhaps something like a structure (or class) containing latitude, longitude and a value. So obviously, class Data cannot hold multiple values or a DataTable. (It contains two strings, key and value).
So what I actually want is the type to be Generic. So I changed it to...
public class MyData<T>
{
public string Name;
public T[] DataItems;
}
So I'll be doing something like this inside the myDAL.GetDataById because what type of data is returned differs according to the type.
if (GetTypeOfId(id) == "NormalData")
{
MyData<Data> result = new MyData<Data>();
}
else if (GetTypeOfId(id) == "Map")
{
MyData<MapData> result = new MyData<MapData>();
}
But I need to specify a type for the method signature as well which unfortunately is found out ONLY at run time.
How do I handle such a situation ?
I feel like I am using Generics for something I shouldn't be using it for.
Or how is usually a situation where the type is found out only at run time resolved?
UPDATE: The worst case scenario is having different web service calls for getting normal data and map data which I would like to avoid.
You can only use generics in circumstances where you can specify the type at compile time, so I don't think they're suitable for your situation.
I would recommend having two web service calls, that's the easiest way to handle this.
If you really want only one web service call you could have your web method simply return a byte[] (created using BinaryFormatter) or a string (created using, say, an XmlSerializer) and then deserialise that on your client side, but it means you have to have the same classes on both sides (or you have to have custom deserialisation code) and your web service can't easily be consumed by multiple clients.
I'm not sure what you are asking for but i have a feeling that using an interface with a generic method could help you pass return values around and call the GetValue generic method on that.
If you use IData instead of a generic type as return value you will be able to extract the embedded data with ret.GetValue<MyData>(). And if you set the Type when creating the Data<T> you will be able to query on that too.
Maybe you can adapt the following snippet to your needs.
public interface IData {
type Type { get; set; }
string Name { get; set; }
T GetValue<T>();
}
public class Data<T> : IData
{
public Type Type { get; set; }
public string Name { get; set; }
public T Value { get; set; }
public Tret GetValue<Tret>() {
return (Tret)(Object)Value;
}
}
The answer was pretty easy and stupid of me not to think of it before.
I just created a parent class and made the Data and all the other required classes inherit from it.