C# 如何可靠地确定在设计时使用var声明的变量的类型?
我正在为C#in emacs开发一个完成(智能感知)设施 其思想是,如果用户键入一个片段,然后通过特定的击键组合请求完成,那么完成工具将使用.NET反射来确定可能的完成 这样做需要知道要完成的事情的类型。如果它是一个字符串,则有一组已知的可能方法和属性;如果它是一个Int32,它有一个单独的集合,依此类推 使用emacs中提供的代码lexer/parser包semantic,我可以找到变量声明及其类型。有鉴于此,使用反射获取类型的方法和属性,然后向用户显示选项列表是很简单的。(好的,在emacs中执行不是很简单,但是使用,它变得简单多了。我编写了一个自定义的.NET程序集来执行反射,将其加载到powershell中,然后在emacs中运行的elisp可以通过comint向powershell发送命令并读取响应。因此,emacs可以快速获得反射的结果。) 当代码在正在完成的事情的声明中使用C# 如何可靠地确定在设计时使用var声明的变量的类型?,c#,reflection,appdomain,type-inference,C#,Reflection,Appdomain,Type Inference,我正在为C#in emacs开发一个完成(智能感知)设施 其思想是,如果用户键入一个片段,然后通过特定的击键组合请求完成,那么完成工具将使用.NET反射来确定可能的完成 这样做需要知道要完成的事情的类型。如果它是一个字符串,则有一组已知的可能方法和属性;如果它是一个Int32,它有一个单独的集合,依此类推 使用emacs中提供的代码lexer/parser包semantic,我可以找到变量声明及其类型。有鉴于此,使用反射获取类型的方法和属性,然后向用户显示选项列表是很简单的。(好的,在emacs
var
时,问题就出现了。这意味着没有显式指定类型,完成将无法工作
使用var
关键字声明变量时,如何可靠地确定实际使用的类型?我只是想说清楚,我不需要在运行时确定它。我想在“设计时”确定它
到目前为止,我有以下想法:
- 提取声明语句,例如'var foo=“字符串值”`李>
- 连接语句`foo.GetType()`李>
- 动态编译生成的C#片段,并将其编译成新的程序集
- 将程序集加载到新的AppDomain中,运行框架并获取返回类型
- 卸载并丢弃部件
编辑-进一步考虑,编译和调用是不可接受的,因为调用可能有副作用。因此,必须排除第一种选择 另外,我认为我不能假设.NET4.0的存在
更新-正确的答案(上文未提及,但Eric Lippert温和地指出)是实现一个全保真度类型推断系统。信息技术这是在设计时可靠确定var类型的唯一方法。但是,这也不容易做到。因为我没有幻想我想尝试构建这样一个东西,所以我选择了选项2的捷径——提取相关的声明代码,并编译它,然后检查生成的IL 对于完成场景的一部分,这实际上是可行的 例如,假设在以下代码片段中?是用户要求完成的位置。这项工作:
var x = "hello there";
x.?
完成操作实现了x是一个字符串,并提供了适当的选项。它通过生成并编译以下源代码来实现这一点:
namespace N1 {
static class dmriiann5he { // randomly-generated class name
static void M1 () {
var x = "hello there";
}
}
}
…然后通过简单反射检查IL
这也适用于:
var x = new XmlDocument();
x.?
引擎将适当的using子句添加到生成的源代码中,以便正确编译,然后IL检查也是一样的
这也行得通:
var x = "hello";
var y = x.ToCharArray();
var z = y.?
这只是意味着IL检查必须找到第三个局部变量的类型,而不是第一个
这是:
var foo = "Tra la la";
var fred = new System.Collections.Generic.List<String>
{
foo,
foo.Length.ToString()
};
var z = fred.Count;
var x = z.?
也不是LINQ语法
我必须考虑这些东西的价值,在我考虑通过绝对的“有限设计”(有礼貌的黑客攻击)来解决这些问题之前。p>
解决依赖于方法参数或实例方法的问题的一种方法是,在生成、编译和分析的代码片段中,用相同类型的“合成”局部变量替换对这些对象的引用
另一个更新-完成依赖于实例成员的变量,现在可以工作了 我所做的是询问类型(通过语义),然后为所有现有成员生成合成替代成员。对于这样的C#缓冲区:
public class CsharpCompletion
{
private static int PrivateStaticField1 = 17;
string InstanceMethod1(int index)
{
...lots of code here...
return result;
}
public void Run(int count)
{
var foo = "this is a string";
var fred = new System.Collections.Generic.List<String>
{
foo,
foo.Length.ToString()
};
var z = fred.Count;
var mmm = count + z + CsharpCompletion.PrivateStaticField1;
var nnn = this.InstanceMethod1(mmm);
var fff = nnn.?
...more code here...
namespace Nsbwhi0rdami {
class CsharpCompletion {
private static int PrivateStaticField1 = default(int);
string InstanceMethod1(int index) { return default(string); }
void M0zpstti30f4 (int count) {
var foo = "this is a string";
var fred = new System.Collections.Generic.List<String> { foo, foo.Length.ToString() };
var z = fred.Count;
var mmm = count + z + CsharpCompletion.PrivateStaticField1;
var nnn = this.InstanceMethod1(mmm);
}
}
}
public类csharp完成
{
私有静态int PrivateStaticField1=17;
字符串InstanceMethod1(整数索引)
{
…这里有很多代码。。。
返回结果;
}
公共无效运行(整数计数)
{
var foo=“这是一个字符串”;
var fred=new System.Collections.Generic.List
{
福,
foo.Length.ToString()
};
var z=fred.Count;
var mmm=count+z+CsharpCompletion.PrivateStaticField1;
var nnn=此.InstanceMethod1(mmm);
变量fff=nnn。?
…这里有更多代码。。。
…编译生成的代码,以便我可以从输出IL中了解本地变量nnn的类型,如下所示:
public class CsharpCompletion
{
private static int PrivateStaticField1 = 17;
string InstanceMethod1(int index)
{
...lots of code here...
return result;
}
public void Run(int count)
{
var foo = "this is a string";
var fred = new System.Collections.Generic.List<String>
{
foo,
foo.Length.ToString()
};
var z = fred.Count;
var mmm = count + z + CsharpCompletion.PrivateStaticField1;
var nnn = this.InstanceMethod1(mmm);
var fff = nnn.?
...more code here...
namespace Nsbwhi0rdami {
class CsharpCompletion {
private static int PrivateStaticField1 = default(int);
string InstanceMethod1(int index) { return default(string); }
void M0zpstti30f4 (int count) {
var foo = "this is a string";
var fred = new System.Collections.Generic.List<String> { foo, foo.Length.ToString() };
var z = fred.Count;
var mmm = count + z + CsharpCompletion.PrivateStaticField1;
var nnn = this.InstanceMethod1(mmm);
}
}
}
名称空间Nsbwhi0rdami{
课程完成{
private static int PrivateStaticField1=默认值(int);
字符串InstanceMethod1(int索引){返回默认值(字符串);}
无效M0zpstti30f4(整数计数){
var foo=“这是一个字符串”;
var fred=new System.Collections.Generic.L
String x = "hello";
var y = x.ToCharArray();
var z = from foo in y where foo.
var z = y.Where(foo=>foo.