[英]Extending a C# interface with common logic without using Extension Methods
Is there a way to extend an interface without using Extension Methods? 有没有不用扩展方法即可扩展接口的方法?
If I define some interface with a couple of get/set strings for example : 如果我用一些get / set字符串定义一些接口,例如:
public interface IMyItem
{
string Title { get; set; }
string Description { get; set; }
}
I'd like add some simple validation to these interfaces, but without having to re-define the logic or force some form of inheritance. 我想对这些接口添加一些简单的验证,但不必重新定义逻辑或强制某种形式的继承。
Currently I'm using Extension Methods, like this : 目前,我正在使用扩展方法,如下所示:
public static class MyItemExtensions
{
public static bool ERROR(this IMyItem item)
{
return item.TITLE_ERROR() || item.DESCRIPTION_ERROR();
}
public static bool TITLE_ERROR(this IMyItem item)
{
return string.IsNullOrEmpty(item.Title);
}
public static bool DESCRIPTION_ERROR(this IMyItem item)
{
return string.IsNullOrEmpty(item.Description);
}
}
Doing this works and I can have: 这样做有效,我可以拥有:
public class Item : IMyItem
{
public string Title { get; set; }
public string Description { get; set; }
}
public static class app
{
public static void go()
{
var item = new Item
{
Title = "My Item Title",
Description = ""
};
Console.log(item.ERROR());
}
}
But I'd prefer ERROR
, TITLE_ERROR
& DESCRIPTION_ERROR
to be get/sets - Is there a way to achieve the same but expose Get/Set properties rather than Extension Methods? 但是我更喜欢将
ERROR
, TITLE_ERROR
和DESCRIPTION_ERROR
TITLE_ERROR
获取/设置-是否可以实现相同的功能,但要公开获取/设置属性而不是扩展方法?
As many have suggested, an abstract
class would be an obvious solution based on the example, but the types need to implement multiple interfaces. 正如许多人所建议的,基于该示例,
abstract
类将是显而易见的解决方案,但是类型需要实现多个接口。
While it may be possible to arrange the inheritance it's an unnecessary complication and restriction on the types. 尽管可以安排继承,但这是不必要的复杂性和类型限制。
The added benefit of using Extension Methods for validation on these interfaces allows for context specific & shared logic to be used, via namespacing. 在这些接口上使用扩展方法进行验证的附加好处是可以通过命名空间使用特定于上下文的共享逻辑。
Multiple ERROR(this IMyItem item)
Extension Methods could be defined for the interface, on different namespaces. 可以为接口在不同的名称空间上定义多个
ERROR(this IMyItem item)
扩展方法。 One that checks Both the TITLE_ERROR
and DESCRIPTION_ERROR
and another might only test one of the properties. 一个同时检查
TITLE_ERROR
和DESCRIPTION_ERROR
,另一个可能只测试其中一个属性。 Then, depending on the context, the relevant namespace can be referenced and the shared validation for that item be executed. 然后,根据上下文,可以引用相关的名称空间,并执行该项目的共享验证。
I'll look at Microsoft's validator, but it looks rather verbose and I really wanted these states as properties for type, as it makes the code that uses them much easier to use. 我将看一下Microsoft的验证器,但是它看起来很冗长,我确实希望这些状态作为类型的属性,因为它使使用它们的代码更易于使用。
Additionally, these are very simple examples, some of the validation much more complex and some cases require interaction with other web services - albeit against a cache of web service data within the AppDomain. 此外,这些都是非常简单的示例,有些验证要复杂得多,有些情况需要与其他Web服务进行交互-尽管是针对AppDomain中的Web服务数据缓存。
Currently these
interface
Extension Methods feel like the best solution.当前,这些
interface
扩展方法感觉是最好的解决方案。
I think a proper solution would be to use an abstract class
instead of an interface
. 我认为适当的解决方案是使用
abstract class
而不是interface
。
What you share here is a common validation logic which will be valid for any class implementing IMyItem
. 您在这里分享的是一个通用的验证逻辑,该逻辑对实现
IMyItem
任何类均有效。 As so, i'd recommand you create an abstract class
as a base for all items, that way they can all reuse that validation code. 因此,我建议您创建一个
abstract class
作为所有项目的基础,这样它们都可以重用该验证代码。 You can even make those properties virtual, so one could extend that validation code: 您甚至可以将这些属性虚拟化,因此可以扩展该验证代码:
public abstract class ItemBase : IMyItem
{
public string cTitle { get; set; }
public string cDescription { get; set; }
public virtual bool Error
{
get { return TitleError || DescriptionError; }
}
public virtual bool TitleError
{
get { return string.IsNullOrEmpty(cTitle); }
}
public virtual bool DescriptionError
{
get { return string.IsNullOrEmpty(cDescription); }
}
}
Seems like you're reinventing the wheel. 似乎您正在重新发明轮子。 Microsoft already created a fairly good validation framework that does not require Entity Framework or MVC.
Microsoft已经创建了一个不需要实体框架或MVC的相当不错的验证框架 。 Simply add a reference to
System.ComponentModel.DataAnnotations
and the using System.ComponentModel.DataAnnotations
to a class: 只需添加一个参考
System.ComponentModel.DataAnnotations
和using System.ComponentModel.DataAnnotations
一类:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public class Program
{
public static void Main()
{
// required if you use the MetdataType attribute
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(typeof(MyItem),
typeof(IMyItemValidation)),
typeof(MyItem));
var item = new MyItem();
var context = new ValidationContext(item,
serviceProvider: null,
items: null);
var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(item, context, results);
if (!isValid)
{
foreach (var validationResult in results)
{
Console.WriteLine(validationResult.ErrorMessage);
}
}
Console.ReadKey();
}
[MetadataType(typeof(IMyItemValidation))]
public class MyItem : IMyItem
{
public string cTitle { get; set; }
public string cDescription { get; set; }
}
public interface IMyItem
{
string cTitle { get; set; }
string cDescription { get; set; }
}
public interface IMyItemValidation
{
[Required]
string cTitle { get; set; }
[Required]
string cDescription { get; set; }
}
/*
// alternatively you could do either of these as well:
// Derive MyItem : MyItemBase
// contains the logic on the base class
public abstract MyItemBase
[Required]
public string cTitle { get; set; }
[Required]
public string cDescription { get; set; }
}
// or
// Derive MyItem : MyItemBase
// contains the logic on the base class using MetadataType
[MetadataType(typeof(IMyItemValidation))]
public abstract MyItemBase
public string cTitle { get; set; }
public string cDescription { get; set; }
}
}
Output 产量
The cTitle field is required.
cTitle字段是必填字段。
the cDescription field is required.
cDescription字段为必填。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.