(首先,这是一个非常冗长的帖子,但不要担心:我已经实现了所有这些,我只是问你的意见,或者可能的替代方案.)
我在实施以下方面遇到了麻烦; 我很感激一些帮助:
Type参数.我在原始类的每个字段中创建一个属性,如下所示:
public class OriginalClass {
private int x;
}
public class Subclass : OriginalClass {
private int x;
public int X {
get { return x; }
set { x = value; }
}
}
Run Code Online (Sandbox Code Playgroud)对于超类的每个方法,我在子类中创建一个类似的方法.该方法的身体必须是除了我更换指令相同的ldfld x有callvirt this.get_X,那就是,而不是从外地直接读取我称之为get访问.
我在第4步遇到了麻烦.我知道你不应该像这样操纵代码,但我真的需要.
这是我尝试过的:
尝试#1:使用Mono.Cecil.这将允许我将方法的主体解析为人类可读的Instructions,并且可以轻松替换指令.但是,原始类型不在.dll文件中,所以我找不到使用Mono.Cecil加载它的方法.将类型写入.dll,然后加载它,然后修改它并将新类型写入磁盘(我认为这是您使用Mono.Cecil创建类型的方式),然后加载它似乎是一个巨大的开销.
尝试#2:使用Mono.Reflection.这也可以让我解析身体Instructions,但后来我不支持更换指令.我使用Mono.Reflection实现了一个非常丑陋且效率低下的解决方案,但是它还不支持包含try-catch语句的方法(虽然我想我可以实现这个)并且我担心可能还有其他场景它不起作用,因为我使用的ILGenerator方式有点不同寻常.而且,它非常丑陋;).这就是我所做的:
private void TransformMethod(MethodInfo methodInfo) {
// Create a method with the same signature.
ParameterInfo[] paramList = methodInfo.GetParameters(); …Run Code Online (Sandbox Code Playgroud) 我正在使用Reflector查看有效方法的IL代码,我遇到了这个问题:
L_00a5: leave.s L_0103
Run Code Online (Sandbox Code Playgroud)
带后缀的指令.s应该采用int8操作数,当然这也应该是Leave_S的情况.但是,0x0103是259,超过了int8的容量.该方法以某种方式工作,但当我用方法读取指令时,Mono.Reflection.Disassembler.GetInstructions它检索
L_00a5: leave.s L_0003
Run Code Online (Sandbox Code Playgroud)
也就是说,3而不是259,因为它应该是一个int8.所以,我的问题是:原始指令(leave.s L_0103)可能如何?我查看了ECMA文档(Partition III:CIL指令集),我找不到任何解释它的东西.
有任何想法吗?谢谢.
编辑#1:好的,我是个白痴.在分支指令的情况下,必须从当前指令之后的指令开始计算偏移量.我发誓我阅读了文档,但不知怎的,我设法跳过了.在我的辩护中,我今天病得很重.叹.
谢谢.(并且感谢你没有称我为白痴,尽管这非常愚蠢:P)
编辑#2:顺便说一句,如果有人感兴趣,当Mono.Reflection.Disassembler.GetInstructions反汇编指令时,它会改变分支指令中操作数的含义.特别是,正如已经指出的那样,分支指令的操作数表示从下一条指令开始的偏移量,而不是从0 Mono.Reflection开始的偏移量.但是,从0 开始返回偏移量(这可能是我感到困惑的原因;虽然它没有解释我是如何设法跳过部分文档的.
提取物MethodBodyReader.ReadOperand(Instruction instruction):
switch (instruction.OpCode.OperandType) {
...
case OperandType.ShortInlineBrTarget:
instruction.Operand = (sbyte) (il.ReadByte () + il.position);
break;
...
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的那样il.position,它是下一条指令的偏移量(从0开始).此外,它投射到sbyte,这是我得到3而不是259的原因.这似乎是一个错误(从0开始的偏移可能大于a sbyte).我会问Jb Evain(作者)并报告.
编辑#3:他还没有回答,但我把它改为:
switch (instruction.OpCode.OperandType) {
...
case OperandType.ShortInlineBrTarget:
instruction.Operand = ((sbyte) il.ReadByte ()) + il.position;
break; …Run Code Online (Sandbox Code Playgroud) 是否有任何 JAXB 绑定可以告诉 JAXB 代码生成器生成 Java 类,而abstract 不必像abstractXSD 中那样标记相应的 XML 类型?
情况如下:
mySchema.xsd我使用内联 JAXB 绑定(“内联”==“直接在架构中”)来指示应在其中生成 JAXB 类的包 ( my.package.jaxb):
<xs:annotation>
<xs:appinfo>
<jxb:schemaBindings>
<jxb:package name="my.package.jaxb"/>
</jxb:schemaBindings>
</xs:appinfo>
</xs:annotation>
Run Code Online (Sandbox Code Playgroud)我使用内联 JAXB 绑定来指示每个复杂类型的实现类的名称(在本例中为my.package.impl.MyAbstractClass、my.package.impl.MyAClass和my.package.impl.MyBClass):
<xs:complexType name="myAbstractType" abstract="true">
<xs:annotation>
<xs:appinfo>
<jxb:class implClass="my.package.impl.MyAbstractClass"/>
</xs:appinfo>
</xs:annotation>
...
</xs:complexType>
<xs:complexType name="myAType">
<xs:annotation>
<xs:appinfo>
<jxb:class implClass="my.package.impl.MyAClass"/>
</xs:appinfo>
</xs:annotation>
<xs:complexContent>
<xs:extension base="myAbstractType">
...
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="myBType">
<xs:annotation>
<xs:appinfo>
<jxb:class implClass="my.package.impl.MyBClass"/>
</xs:appinfo> …Run Code Online (Sandbox Code Playgroud)我正在编写一个系统,它是程序员应用程序的基础,需要检测他们对某些数据的访问.我几乎可以使用属性这样做,如下所示:
public class NiceClass {
public int x { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后我进入并调整get和set访问器,以便他们适当地处理访问.但是,这要求用户(应用程序编程人员)将其所有数据定义为属性.
如果用户想要使用具有"正常"字段的预先存在的类(而不是属性),我无法检测到这些访问.例:
public class NotSoNiceClass {
public int y;
}
Run Code Online (Sandbox Code Playgroud)
我无法检测到访问y.但是,我想允许使用预先存在的类.作为折衷方案,用户有责任在访问此类数据时通知我.例如:
NotSoNiceClass notSoNice;
...
Write(notSoNice.y, 0); // (as opposed to notSoNice.y = 0;)
Run Code Online (Sandbox Code Playgroud)
这样的事情.相信我,我已经非常彻底地研究了这一点,甚至直接分析字节码以检测访问因可能的间接性等而不可靠.我确实需要用户通知我.
现在我的问题是:你能推荐一种"优雅"的方式来执行这些通知吗?(是的,我知道这种情况一开始并不"优雅";我试图不让它变得更糟;)).你会怎么做?
这对我来说是个问题,因为实际上情况是这样的:我有以下课程:
public class SemiNiceClass {
public NotSoNiceClass notSoNice { get; set; }
public int z { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果用户想要这样做:
SemiNiceClass semiNice;
...
semiNice.notSoNice.y = 0;
Run Code Online (Sandbox Code Playgroud)
他们必须做这样的事情:
semiNice.Write("notSoNice").y = 0;
Run Code Online (Sandbox Code Playgroud)
哪里Write会返回克隆 …
这是一个非常多余和无趣的问题,我很害怕,但我总是对此感到疑惑.当您使用内联注释(而不是将生成的文档中出现的注释)注释代码时,注释中会显示变量的名称,您如何将其与普通文本区分开来?例如:
// Try to parse type.
parsedType = tryParse(type);
Run Code Online (Sandbox Code Playgroud)
在注释中,"type"是变量的名称.您是否以任何方式标记它是否表示它是符号而不仅仅是评论文本的一部分?我见过这样的事情:
// Try to parse "type".
// Try to parse 'type'.
// Try to parse *type*.
// Try to parse <type>.
// Try to parse [type].
Run Code Online (Sandbox Code Playgroud)
并且:
// Try to parse variable type.
Run Code Online (Sandbox Code Playgroud)
(我不认为最后一个是非常有用的;它有点令人困惑;你可以认为"变量"是一个形容词)
你有什么偏好吗?我发现我需要使用某种标记; 否则评论有时会模棱两可,或者当你意识到评论中的特定单词实际上是变量的名称时,至少会强迫你重新阅读它们.
(在文档中出现的注释中,我使用适当的生成器标签,当然:@ code,<code> </ code>等)
谢谢!
对于词汇问题我很抱歉,但我无法在任何地方找到这个问题:你怎么称呼这个?
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyAssembly")]
Run Code Online (Sandbox Code Playgroud)
这是一个声明,一个指令,......?我想表明你必须插入该行才能MyAssembly访问你的程序集internal成员,但是我想使用比"line"更具体的术语.
谢谢!
首先,对标题感到抱歉 - 我无法弄清楚那个短而清晰的标题.
这是问题:我有一个列表List<MyClass> list,我总是添加新创建的实例MyClass,如下所示:list.Add(new MyClass()).我不以任何其他方式添加元素.
但是,然后我遍历列表foreach并发现有一些空条目.也就是说,以下代码:
foreach (MyClass entry in list)
if (entry == null)
throw new Exception("null entry!");
Run Code Online (Sandbox Code Playgroud)
有时会抛出异常.我应该指出,这些list.Add(new MyClass())是从同时运行的不同线程执行的.我能想到的唯一考虑null条目的是并发访问.List<>毕竟,这不是线程安全的.虽然我仍然觉得奇怪的是它最终包含空条目,而不是在订购时不提供任何保证.
你能想到其他任何原因吗?
此外,我不关心添加项目的顺序,我不希望调用线程阻止等待添加其项目.如果同步确实是问题,你能推荐一种简单的方法来Add异步调用该方法,即创建一个委托,在我的线程继续运行其代码时处理它吗?我知道我可以创建一个代表Add并调用BeginInvoke它.这看起来合适吗?
谢谢.
编辑:一个基于凯文的建议的简单解决方案:
public class AsynchronousList<T> : List<T> {
private AddDelegate addDelegate;
public delegate void AddDelegate(T item);
public AsynchronousList() {
addDelegate = new AddDelegate(this.AddBlocking);
}
public void AddAsynchronous(T item) {
addDelegate.BeginInvoke(item, null, null);
}
private void …Run Code Online (Sandbox Code Playgroud) 我觉得这是我应该知道的,但是java代理(用-javaagent指定)是否在一个单独的线程中运行?我已经读过Java代理是一个可嵌入的库,它运行嵌入在JVM中并拦截了类加载过程,但我想确定:它是否真的拦截它们(这听起来像是在另一个线程中运行并监视类加载)或者它是否由JVM通知(JVM调用它来解析类加载;它没有单独的线程)?
再一次,我觉得我应该能够弄明白,但对我好,我工作太辛苦了,我的大脑有点油炸:P
谢谢!
c# ×5
reflection ×2
.net ×1
assemblies ×1
asynchronous ×1
attributes ×1
binding ×1
cil ×1
coding-style ×1
comments ×1
field ×1
identifier ×1
il ×1
java ×1
javaagents ×1
jaxb ×1
jvm ×1
list ×1
magic-string ×1
mono.cecil ×1
null ×1
terminology ×1
xjc ×1
xml ×1