C# 在c中强制实现没有接口或抽象类的方法#

C# 在c中强制实现没有接口或抽象类的方法#,c#,wpf,class,xaml,C#,Wpf,Class,Xaml,我正在创建一个模块化系统,当一个应用程序(主机)将其他模块加载到一个通用UI界面时,我还为此创建了一个API,可供其他用户使用 在某些情况下,API使用接口和抽象类强制使用API的客户端实现特定方法 我不能将接口用于所有事情,因为有些事情我需要放在自己的身体中,这样最终用户就不需要自己实现所有不必要的事件和方法。因此,我自己处理大小更改事件,然后将大小传递给他实现的一个名为SizeChanged的函数,前提是他可以处理大小更改中的程序 抽象类是我真正想要使用的,但我不能,因为用户拥有的控件可能需

我正在创建一个模块化系统,当一个应用程序(主机)将其他模块加载到一个通用UI界面时,我还为此创建了一个API,可供其他用户使用

在某些情况下,API使用接口和抽象类强制使用API的客户端实现特定方法

我不能将接口用于所有事情,因为有些事情我需要放在自己的身体中,这样最终用户就不需要自己实现所有不必要的事件和方法。因此,我自己处理大小更改事件,然后将大小传递给他实现的一个名为SizeChanged的函数,前提是他可以处理大小更改中的程序

抽象类是我真正想要使用的,但我不能,因为用户拥有的控件可能需要在XAML中指定的x:Name,并且将收到错误:

类型。。。不能有名称属性。值类型和没有默认构造函数的类型可以用作ResourceDictionary中的项

发生此错误是因为需要创建其实例:

据我所知,唯一可用的解决方案是使用一个带有虚拟方法的常规类,该类可以被重写,并且工作正常,但不会强制用户实现所需的方法

有什么我可以干净利落地做的,比如任何公共的可实现的或什么的吗

结构如下:

API: IContext->ContextControl->(抽象方法)

模块动态链接库 ContextControl(API)->AppContextControl(重写方法)

主机应用程序拉取的AppContextControl

我知道我可以告诉模块开发人员实现一个接口以及这个限制他们实现接口的ContextControl,但是编译器告诉他们会更加专业

在dev模块中,如果我没有继承ContextControl,而是实现了IContext,那么我将丢失所有默认的body,模块dev将实现更多


干杯。

您所描述的两种方法-接口和抽象类-是(我相信您知道的)执行您所描述的操作的推荐方法,至少,如果您希望在编译时强制实现的话


我知道的唯一其他方法是提供一个默认实现,该实现抛出一个
NotImplementedException()
。这将给您一个运行时错误,但不幸的是在编译时没有任何错误。

您不能结合使用继承和接口吗?换句话说,为可以被覆盖的方法创建
virtual
方法,并使用接口实现必须被覆盖的方法?

这可能适用于您的特定情况,也可能不适用于您的特定情况,但另一种可能的绕过限制的方法是使用策略模式


与其让用户重写成员,不如让他们将包含功能的参数传递给构造函数。这可能是作为委托,也可能是您为此目的创建的特定类。

我最近遇到了类似的问题(我不知道这对您的情况会有帮助)。在这里,我必须在编译时而不是运行时生成错误,使用通用功能。我使用的方法是和的结合。例如

1) 枚举示例:() 问题是设置一些东西,这样我就不必在整个项目中实现每一个代码并强制构造函数

public abstract class EnumEx<T> where T : EnumEx<T>
{
    private readonly string _displayValue;
    private readonly string _value;

    protected static ReadOnlyCollection<T> EnumExs;

    protected EnumEx(string displayValue, string value)
    {
        _displayValue = displayValue;
        _value = value;
    }

    public string DisplayValue
    {
        get { return _displayValue; }
    }

    public static T FromString(string option)
    {
        foreach (var enumEx in EnumExs.Where(enumEx => enumEx._value == option))
        {
            return enumEx;
        }
        Debug.WriteLine(string.Format("Exception in EnumEX FromString({0})", option));
        return null;
    }

    public override string ToString()
    {
        return _value ?? string.Empty;
    }
}
公共抽象类EnumEx,其中T:EnumEx
{
私有只读字符串_displayValue;
私有只读字符串_值;
受保护的静态只读集合枚举;
受保护的EnumEx(字符串显示值、字符串值)
{
_displayValue=displayValue;
_价值=价值;
}
公共字符串显示值
{
获取{return\u displayValue;}
}
公共静态T FromString(字符串选项)
{
foreach(EnumExs.Where中的var enumEx(enumEx=>enumEx.\u value==option))
{
返回enumEx;
}
WriteLine(string.Format(“EnumEX FromString({0})中的异常”,选项));
返回null;
}
公共重写字符串ToString()
{
返回_值??字符串。为空;
}
}
2) 深度复制()+可编辑实现自定义列表

public abstract class CloneAbleBase<T> : ObservableObjectEx, ICloneable, IEditableObject
    where T : DataBase<T>, new()
{
    protected T CurrentData = new T();
    private T _backupData;
    private bool _isInEditMode;

    public object Clone()
    {
        var dataObject = (CloneAbleBase<T>) MemberwiseClone();
        dataObject.CurrentData = CurrentData.Copy();
        return dataObject;
    }

    public void BeginEdit()
    {
        if (_isInEditMode) return;
        _backupData = CurrentData.Copy();
        _isInEditMode = true;
    }

    public void EndEdit()
    {
        if (!_isInEditMode) return;
        _backupData = default(T);
        _isInEditMode = false;
        RaisePropertyChanged(string.Empty);
    }

    public void CancelEdit()
    {
        if (!_isInEditMode) return;
        CurrentData = _backupData;
        RaisePropertyChanged(string.Empty);
    }
}
公共抽象类CloneAbleBase:observeObjectEx、IClonable、IEditableObject
其中T:DataBase,new()
{
受保护的T CurrentData=新的T();
私人T_backupdatea;
私有bool_isInEditMode;
公共对象克隆()
{
var dataObject=(CloneAbleBase)MemberwiseClone();
dataObject.CurrentData=CurrentData.Copy();
返回数据对象;
}
public void BeginEdit()
{
如果(_isInEditMode)返回;
_BackUpdatea=CurrentData.Copy();
_isInEditMode=true;
}
公共无效EndEdit()
{
如果(!\u isInEditMode)返回;
_backupdatea=默认值(T);
_isInEditMode=false;
RaisePropertyChanged(string.Empty);
}
公共作废取消编辑()
{
如果(!\u isInEditMode)返回;
CurrentData=\u backupdatea;
RaisePropertyChanged(string.Empty);
}
}

以类似的方式,您可以为您的
窗口或任何控件创建基类,在这些控件中,您需要一些功能某种通用功能。

在您非常特定的情况下,我可以看到另一种方法是使用接口(正如您所说,它不允许您插入自己的代码)然后从最终用户提供并作为接口传入的实际类型继承,并在运行时将您自己的代码注入其中

例如,加载所有实现IMyPlugin的类

public interface IMyPlugin{
   void MyEndUserMethod();
   void YourMethod();
}
用户实现从中继承的类

public class UserClass:IMyPlugin{
....
}
您希望强制使用自己的代码而不是方法,然后在运行时生成一个从UserClass继承的类,并在
public interface IPlugin : IUserPlugin,ICreatorPlugin