如何让 protected internal 跨程序集!

颤菊大师 2011-01-19 03:08:54
项目A(ClassLibrary1):
有一个类:

namespace ClassLibrary1
{
public abstract class HelloBase
{
protected internal abstract void SayHello();
}
}



注意 SayHello 的访问修饰符:protected internal abstract。

这个原意可能有两个版本:
1、允许 ClassLibrary1 程序集访问 HelloBase.SayHello 或者让派生类(其他程序集)访问(靠谱)。
2、允许 ClassLibrary1 程序集以及所派生的程序集进行访问(显然不靠谱)。

是的,我在其他程序集引用了 ClassLibrary1 并继承 HelloBase
通过 VS 2010 的快捷方式,我得到了:

public class HelloClass : ClassLibrary1.HelloBase
{
protected override void SayHello()
{
Console.WriteLine("Hello");
}
}

显然这是没错的。可是,为什么我在研究别人的源码时,发现已编译的程序集竟然存在:

public class HelloClass : ClassLibrary1.HelloBase
{
protected internal override void SayHello()
{
Console.WriteLine("Hello");
}
}


那么,我该如何让它编译成功?
VS2010 的错误提示如下:

错误
“ConsoleTest.HelloClass.SayHello()”: 当重写“protected”继承成员“ClassLibrary1.HelloBase.SayHello()”时,无法更改访问修饰符
...全文
552 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
eisai2000 2011-06-09
  • 打赏
  • 举报
回复
An interesting assembly-level attribute introduced by .NET 2.0 is the InternalsVisibleTo attribute, defined in the System.Runtime.CompilerServices namespace. This attribute allows you to expose internal types and methods to clients from another specified assembly. This is also known as declaring a friend assembly. For example, suppose the server assembly MyClassLibrary.dll defines the internal class MyInternalClass as:

internal class MyInternalClass
{
public void MyPublicMethod( )
{...}
internal void MyInternalMethod( )
{...}
}



If you add this line to the AssemblyInfo.cs file of MyClassLibrary.dll:

[assembly: InternalsVisibleTo("MyClient")]



any client in the assemblies MyClient.dll and MyClient.exe will be able to use MyInternalClass and call its public or internal members. In addition, any subclass in the MyClient assembly will be able to access members marked as protected internal.
颤菊大师 2011-01-24
  • 打赏
  • 举报
回复
有一个程序集特性……可以实现这样的效果。
也就是C#版的“友元”!结贴!
showjancn 2011-01-20
  • 打赏
  • 举报
回复
楼主给的图,从反编译的情况来看,确实是这么回事的。

但从理论上说是应该编译不过。很可惜手头没有10.2的源码。

DecExpress确实很喜欢用protected internal;我看了手头7.3的源码,全工程并没有出现这种有违语法的现象。(注:7.3没有RichEdit,我只参参考RichText)。

经过代码发现:DEV中有很多“protected internal new”的实现。

另一种可能,会不会Dev把相关代码进行了混淆(我想应该不会,如果这样还不如加密)。
qldsrx 2011-01-19
  • 打赏
  • 举报
回复
灰太狼你好,看到你7楼给的图,知道你要问什么了。
你只注意了那个程序集,但是忽略了命名空间,仔细看下那两个类虽然不是同一个程序集,但是命名空间都一样,都是“DevExpress.XtraRichEdit.Layout.Export”命名空间哦,哈哈!
颤菊大师 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 gomoku 的回复:]

引用 18 楼 mrlen 的回复:


protected不带internal的区别就是从当前的程序集非继承不能调用。
如果你不只是好奇,还想要得到internal的效果,那么可以添加一个转发函数,来达到同样的目的:
C# code

public class Hello : ClassLibrary1.HelloBase
{
protected override void……
[/Quote]

gomoku ,十分感谢您的积极回复。您的精神很令我感动。
我最终还是决定将所有的 protected internal 转换为 public。这个改动量比较小
gomoku 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 mrlen 的回复:]
[/Quote]

protected不带internal的区别就是从当前的程序集非继承不能调用。
如果你不只是好奇,还想要得到internal的效果,那么可以添加一个转发函数,来达到同样的目的:

public class Hello : ClassLibrary1.HelloBase
{
protected override void SayHello()
{
}

internal void SayHelloInternal() //<---
{
this.SayHello();
}
}

颤菊大师 2011-01-19
  • 打赏
  • 举报
回复
显然,只有将所有的 protected internal 全部改成 public 才是解决之道啊……
颤菊大师 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 gomoku 的回复:]

"编译器错误 CS0507"说的是C#编译器。其他编译器可能不采用该规则。
比如下面代码将编译出internal protected(注意famorassem修饰):
Assembly code

//
// hello.il
// 编译命令:ilasm /dll hello.il
// 需要当前目录有程序集ClassLibrary1.dll
//
.assembly extern Cla……
[/Quote]

无法让 VS2010 忽略这个错误?或“跳过”、“绕过”检查?
gomoku 2011-01-19
  • 打赏
  • 举报
回复
"编译器错误 CS0507"说的是C#编译器。其他编译器可能不采用该规则。
比如下面代码将编译出internal protected(注意famorassem修饰):

//
// hello.il
// 编译命令:ilasm /dll hello.il
// 需要当前目录有程序集ClassLibrary1.dll
//
.assembly extern ClassLibrary1{}
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
.ver 2:0:0:0
}

.assembly ClassLibrary2{}
.module ClassLibrary2.dll
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY

.class public auto ansi beforefieldinit Hello
extends [ClassLibrary1]ClassLibrary1.HelloBase
{
.method famorassem hidebysig virtual instance void
SayHello() cil managed
{
ret
}

.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [ClassLibrary1]ClassLibrary1.HelloBase::.ctor()
ret
}
}
颤菊大师 2011-01-19
  • 打赏
  • 举报
回复
难道是这个起了作用?


/addmodule(导入元数据)
颤菊大师 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 vrhero 的回复:]

Reflector显示的未必就是正确的...它是通过反射得到其元数据,只是显示其具有那些修饰符...然而你在代码中不可以更改基类方法的访问修饰符,不允许显式声明...
[/Quote]

vrhero,可是我的源码包也是这样。其他的源码都正常,偏偏这个项目上会存在这个问题?
然后是“故意的捣蛋”?
macooidle 2011-01-19
  • 打赏
  • 举报
回复
lz可以尝试自己写一个,然后用reflector看看结果,可能就会出现这样的情况了
vrhero 2011-01-19
  • 打赏
  • 举报
回复
Reflector显示的未必就是正确的...它是通过反射得到其元数据,只是显示其具有那些修饰符...然而你在代码中不可以更改基类方法的访问修饰符,不允许显式声明...
gomoku 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用楼主 mrlen 的回复:]
...
可是,为什么我在研究别人的源码时,发现已编译的程序集竟然存在:
public class HelloClass : ClassLibrary1.HelloBase
{
protected internal override void SayHello()
{
Console.WriteLine("Hello");
}
}
...
[/Quote]

如果从同一个assembly内进行继承,是继续用protected internal修饰。
颤菊大师 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 zhgroup 的回复:]

devexpress能编译通过,他是在编译检查上做修改了吧?
[/Quote]
我猜测也是这样。这样很纠结啊!不知道有没有办法绕过编译检查!
zhgroup 2011-01-19
  • 打赏
  • 举报
回复
devexpress能编译通过,他是在编译检查上做修改了吧?
颤菊大师 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jjx0224 的回复:]

你想问的我没太看懂

2、允许 ClassLibrary1 程序集以及所派生的程序集进行访问(显然不靠谱)。

这句话怎么不靠谱了?

protected internal 本来就是可以在当前程序集中用,并且在其他程序集中的派生类也可以使用

你那个错误:因为你继承时,覆写SayHello()函数时,和父类SayHello()的签名不同
[/Quote]

我指的不靠谱是,仅限于“其他程序集的派生类访问”,而非“其他程序集访问”。
颤菊大师 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 qldsrx 的回复:]

你为啥要多一个internal 修饰啊。
[/Quote]

这并不是“我要”,而是不理解“为什么这样能够编译成功”?
颤菊大师 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 vrhero 的回复:]

哪里来的两个版本...别想当然,MSDN早就有明确地解释...
引用 MSDN:protected internal 访问仅限于从包含类派生的当前程序集或类型。
[/Quote]

vrhero,这个我明白的。但是我不理解,别人是怎么实现这样的方式?
我直接上图:
---------------------
抽象类:

---------------------
派生类:


qldsrx 2011-01-19
  • 打赏
  • 举报
回复
你为啥要多一个internal 修饰啊。
加载更多回复(5)
内容概要:本文针对无刷直流电机驱动的电子机械制动(EMB)执行器,建立了考虑Stribeck摩擦特性的非线性耦合动力学模型,并在Simulink环境中完成了系统级仿真分析。研究综合成了电机动力学、齿轮传动机构与制动执行机构的动力学特性,构建了高保真的机电一体化系统模型。重点引入Stribeck摩擦模型以精确描述低速工况下执行器内部存在的静摩擦、粘滞摩擦与库仑摩擦之间的过渡行为,有效提升了系统在启停、反向运动等瞬态过程中的动态响应仿真精度。通过多工况仿真验证了模型的有效性,能够准确反映摩擦引起的爬行、滞后与定位误差等非线性现象,为EMB系统的高性能控制算法设计(如摩擦补偿、滑模控制)与结构优化提供了高可信度的仿真平台。; 适合人群:从事汽车电子制动系统、电机驱动控制、机电系统建模与仿真研究的研究生、科研人员及工程技术人员,需具备扎实的机械动力学、自动控制理论基础和MATLAB/Simulink仿真能力。; 使用场景及目标:①用于高精度电子机械制动系统的设计验证与性能预测;②为消除摩擦非线性影响的先进控制策略(如自适应控制、智能控制)提供精确的被控对象模型;③深入探究Stribeck摩擦等非线性因素对系统动态性能(如响应延迟、稳态误差)的作用机理; 阅读建议:读者应结合提供的Simulink模型文件,深入剖析Stribeck摩擦模块的数学实现与参数辨识方法,建议通过改变输入指令(如阶跃、正弦)和负载条件进行对比仿真,以直观理解非线性摩擦对系统动态特性的影响。

111,129

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧