我目前正在努力理解我应该如何组织/构建一个我已经创建的类。该课程执行以下操作:
以下是一些描述我正在做的事情的简化代码:
class FilteredCollection
{
public FilteredCollection( SpecialArray<MyLog> myLog)
{
// validate inputs
// filter and validate logs in collection
// in end, FilteredLogs is ready for access
}
Public List<MyLog> FilteredLogs{ get; private set;}
}
但是,为了访问此集合,我必须执行以下操作:
var filteredCollection = new FilteredCollection( specialArrayInput );
//Example of accessing data
filteredCollection.FilteredLogs[5].MyLogData;
其他关键输入:
我知道这里可能没有“完美”的解决方案,但我真的想通过这种设计来提高我的技能,我非常感谢这样做的建议。提前致谢。
修改
感谢所有的回答者,Dynami Le-Savard和Heinzi都确定了我最终使用的方法 - 扩展方法。我最终创建了一个MyLogsFilter静态类
namespace MyNamespace.BusinessLogic.Filtering
{
public static class MyLogsFilter
{
public static IList<MyLog> Filter(this SpecialArray<MyLog> array)
{
// filter and validate logs in collection
// in end, return filtered logs, as an enumerable
}
}
}
我可以通过
在代码中创建一个只读集合IList<MyLog> filteredLogs = specialArrayInput.Filter();
ReadOnlyCollection<MyLog> readOnlyFilteredLogs = new ReadOnlyCollection<MyLog>(filteredLogs);
答案 0 :(得分:3)
听起来你对日志做了三件事:
您希望将日志存储在集合中。标准的List集合非常适合,因为它不关心它的内容,为您提供LINQ并允许您使用只读包装器锁定集合
我建议你将你的顾虑分成上面的三个步骤。
考虑
interface ILog
{
MarkAsValid(bool isValid);
... whatever data you need to access...
}
将验证逻辑放在单独的接口类
中interface ILogValidator
{
Validate(ILog);
}
你的过滤逻辑在另一个
interface ILogFilter
{
Accept(ILog);
}
然后使用LINQ,类似于:
List<MyLog> myLogs = GetInitialListOfLogsFromSomeExternalSystem();
myLogs.ForEach(x => MyLogValidator(x));
List<MyLog> myFilteredLogs = myLogs.Where(x => MyLogFilter(x));
关注点分离使测试和可维护性更好。并远离单身人士。由于包括可测试性在内的许多原因,它们都不受欢迎。
答案 1 :(得分:1)
一些想法:
正如您正确指出的那样,使用实例类可以提高可测试性。
如果(A)整个系统中只有一个类的实例和(B),您需要在应用程序的多个不同位置访问此实例时使用单例无需传递物体。应该避免不必要地使用Singleton模式(或任何其他类型的“全局状态”),所以除非(B)在你的情况下也满足,否则我不会在这里使用单例。
对于简单的解除引用,请考虑使用indexer。这将允许您写:
FilteredCollection filteredlogs = new FilteredCollection( secialArrayInput ); //Example of accessing data filteredlogs[5].MyLogData;
SpecialArray<MyLog>
{{1}},允许您像这样访问它:List<MyLog> filteredlogs = secialArrayInput.Filter(); //Example of accessing data filteredlogs[5].MyLogData;
答案 2 :(得分:1)
我看到它的方式,您正在查看一个返回过滤日志集合的方法,而不是包含业务逻辑的集合类。像这样:
class SpecialArray<T>
{
[...]
public IEnumerable<T> Filter()
{
// validate inputs
// filter and validate logs in collection
// in end, return filtered logs, as an enumerable
}
[...]
}
然而,看起来你真正希望将实际上分离负责过滤日志的业务逻辑与SpecialArray
类分开,可能是因为你觉得这个逻辑涉及许多并不是真正关心的事情SpecialArray
,或Filter
不适用于SpecialArray
的所有通用案例。
在这种情况下,我的建议是将您的业务逻辑隔离在另一个namespace
中,可能是使用和/或需要其他组件以应用所述业务逻辑,并提供您的功能作为扩展方法,具体地说:
namespace MyNamespace.Collections
{
public class SpecialArray<T>
{
// Shenanigans
}
}
namespace MyNamespace.BusinessLogic.Filtering
{
public static class SpecialArrayExtensions
{
public static IEnumerable<T> Filter<T>(this SpecialArray<T> array)
{
// validate inputs
// filter and validate logs in collection
// in end, return filtered logs, as an enumerable
}
}
}
当您需要使用该业务逻辑时,它看起来像这样:
using MyNamespace.Collections; // to use SpecialArray
using MyNamespace.BusinessLogic.Filtering; // to use custom log filtering business logic
namespace MyNamespace
{
public static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main2()
{
SpecialArray<Logs> logs;
var filteredLogs = logs.Filter();
}
}
}
答案 3 :(得分:0)
如果要为最终过滤的数组继承SpecialArray的接口,则从具有实例成员的SpecialArray instad派生。这将允许:
filteredCollecction [5] .MyLogData;
等。