C# design question [closed]
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this questionI started designing a small application and have some architecture-related questions.
I have some basic entities, which I'm willing to model - Repository
and Indicator
.
Repository
is basically a facade using the Repository Pattern
, which is able to retrieve / store arbitrary entities using some database holder (right now it's NHibernate
-driven, but I guess that's not actually important).
The Indicator
may be called the logical core of my application. It is used to combine abstract values and the exact time at which that value was achieved (so it forms and operates on Value - Time
pairs).
I am willing to make this Indicator
as generic as possible, still I think my current solution is开发者_如何学运维 a big fail :)
See the following chunks of code:
public interface IIndicator<T>
{
IEnumerable<T> RetrieveValues(DateTime start, DateTime end);
}
// Should also have something like indicator wrapper / proxy stub here - anything
// that represents the 'IIndicator' interface acts through that proxy and
// caches the evaluated data using it.
This is a basic attempt to implement the indicator (right now this can actually be considered as a mock):
public class Indicator<TValue> :
// Self-referencing generic parameter.
IIndicator<Indicator<TValue>.TimestampProxy>
{
// Proxy, which is used to add the timestamp to
// every indicated value.
public class TimestampProxy
{
public TValue Value;
public DateTime Time;
public TimestampProxy(DateTime time, TValue value)
{
Time = time;
Value = value;
}
}
private readonly IRepository repository;
public Indicator(IRepository repository)
{
this.repository = repository;
}
public IEnumerable<TimestampProxy> RetrieveValues(DateTime start, DateTime end)
{
// Note the custom time stamp comparation in the lambda
// expression. Comparation includes the 'start' and 'end' limits.
IQueryable<TimestampProxy> queryable = repository.Retrieve<TimestampProxy>(
x => x.Time.CompareTo(start) >= 0 && x.Time.CompareTo(end) <= 0);
return queryable.ToList();
}
}
Now - this might look fine, but I'm absolutely sure that the TimestampProxy
used is really evil.
It also makes the things hard to understand (for example, method signature IEnumerable<TimestampProxy> RetrieveValues(...)
would probably result in a "wtf?!" phrase from a person who examines the code).
Unfortunately, I can't come up with a better solution / global redesign - could you advice me how to do it or simply tell some ideas about how this kind of feature should be done?
Thanks.
How about refactoring the RetrieveValues method back into the Repository itself and going with a much simpler Indicator class that basically replaces your TimestampProxy class.
public class Indicator<T>
{
public DateTime Timestamp { get; set; }
public T Value { get; set; }
}
public class Repository
{
public IEnumerable<Indicator<T>> RetrieveIndicators<T>( DateTime start, DateTime end )
{
// determine table to query based on type T
// query and convert objects to Indicator<T>
// return collection
}
}
One thing that bothers me is that in making it generic you've lost the connection to the DB table. It might be better to simply define an interface that all of your specific DB objects implement and use partial implementations to map the actual "value" onto the Value property.
public interface Indicator<T>
{
DateTime Timestamp { get; }
T Value { get; }
}
public partial class TemperatureIndicator : Indicator<double>
{
public double Value { get { return this.Temperature; } }
}
Now have your repository implement methods that return objects of each type -- which can be used as (in .NET 4 or cast to in lower versions) objects of the interface type for common operations.
精彩评论