开发者

C# design question [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.

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 question

I 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜