2012-09-13 39 views
7

有没有一种方法可以有条件地应用属性结构?基于不同的结构属性的32位或64位

如果机器32位我想如果机器应用此属性

[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Unicode)]

我想申请这个属性

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]

或可替代我可以用属性...

0123替换一个值吗?

32位(包= 2)

[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Unicode)]

(包= 8)

[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)]

我试图用这个example但它的自定义属性,不存在那些。

更新:

  • 我想comile到“任何CPU”
  • 的属性是SHFILEOPSTRUCT并根据在所述处理器上使用或。
  • 我不想编译两个版本。
+1

你会静态编译程序64位和32位,还是你使用“任何CPU”,并希望在运行时表现不同? –

+0

如果只有'StructLayoutAttribute'类没有密封。卫生署! – simonlchilds

+1

你可以用条件编译指令来做到这一点。 –

回答

6

好问题。

我首先想到的答案是预处理器指令和32位和64位编译程序集。您可以使用相同的代码,即使是同一个项目,只是构建和部署根据目标系统上有两个途径:

#ifdef Bit32 
[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Unicode)] 
#endif 
#ifdef Bit64 
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)] 
#endif 

这需要定义一个基于目标架构为您的项目Bit32和Bit64编译常数,并可能构建你的应用程序两次。

如果你想在运行时做到这一点,我不认为这是可能的,除非你在运行时动态地发出整个类。这些属性可能只有固定的数据,并且它们不能在运行时有条件地应用(预处理器指令在编译时运行,而不是在运行时运行)。

我认为可以这样做的唯一方法是将类定义复制到两个名称空间中,并根据Environment.Is64BitOperatingSystem属性有条件地使用其中一个或另一个。您可以使用此属性来有条件地控制您实例化哪个类,或选择哪种创建策略(使用哪种工厂方法或相关模式),但不能在运行时条件控制属性;他们的信息作为元数据静态编译到程序集清单中。运行时本身特别使用这个特性来定义它如何将堆对象的成员存储为堆数据,并且您从未真正在用户代码中查找此属性并使用它来定义行为(从而忽略或指定条件包运行时的值)。

+0

+1。在运行时发出听起来像有趣的方法。 –

+0

有趣的是,在卧室里捆绑和ch咽的方式很有趣,绝对需要一定的心态才能这样看待。 – KeithS

+0

是的,我应该更仔细地选择我的话 - 在“令人兴奋的,有趣的,冒险的,但不太可能有利可图”的乐趣。我认为“捆绑和窒息”是比较严酷的比较,除非是因为真正的生产代码决定采用这种方法。 –

0

我不认为你可以这样做。只是有2个结构,并提供了一种方法来转换为共享结构或类处理...

注意:你要求的功能是非常奇怪的(不同的基于JIT类型的显式布局,发生在运行时)。在大多数情况下,这用于字节的物理布局,匹配一些众所周知的独立于应用程序的固定协议。您可以将您的案例视为针对x86/x64情况具有2种不同的协议/ interop,并对2种结构感到满意。

1

创建两个不同的构建目标(一个用于32位,一个用于64位),为每个(x86为一个,x86_64为另一个)添加一个条件编译符号,并围绕结构定义使用#ifdef

+0

没有更多upvotes:(....我认为这种方法将工作 - 编译相同的类/结构的2个版本,并在运行时动态加载一个取决于当前进程的位。这样你有一个结构/类和可以很容易地在代码的其余部分使用它,而不会奇怪ifdefs –

+0

@Alexei Levenkov - 应该说,我不是真的想编译两个版本。 – Rob