C
C#11mo ago
jborean

Create dynamic class that implements interface with static properties

Sorry for the PowerShell but I'm trying to figure out how to create a class that implements an interface with a static property and I have the following
using namespace System.Reflection
using namespace System.Reflection.Emit

$ErrorActionPreference = 'Stop'

Add-Type -TypeDefinition @'
public interface IProperty
{
static abstract int Id { get; }
}

public class CSharpProperty : IProperty
{
public static int Id { get => 1; }
}
'@

$ab = [AssemblyBuilder]::DefineDynamicAssembly(
[AssemblyName]::new("MyAssembly"),
[AssemblyBuilderAccess]::Run)
$mb = $ab.DefineDynamicModule("MyModule")
$tb = $mb.DefineType(
"MyClass",
[TypeAttributes]::Public,
$null,
[type[]]@([IProperty]))

$getAttr = $tb.DefineMethod(
"get_Id",
[MethodAttributes]"Public, Static, HideBySig, SpecialName",
[int],
[type]::EmptyTypes)
$getAttrIl = $getAttr.GetILGenerator()
$getAttrIl.Emit([OpCodes]::Ldc_I4_1)
$getAttrIL.Emit([OpCodes]::Ret)

$pb = $tb.DefineProperty(
"Id",
[PropertyAttributes]::None,
[int],
$null)
$pb.SetGetMethod($getAttr)

$null = $tb.CreateType()

[MyClass]::Id
using namespace System.Reflection
using namespace System.Reflection.Emit

$ErrorActionPreference = 'Stop'

Add-Type -TypeDefinition @'
public interface IProperty
{
static abstract int Id { get; }
}

public class CSharpProperty : IProperty
{
public static int Id { get => 1; }
}
'@

$ab = [AssemblyBuilder]::DefineDynamicAssembly(
[AssemblyName]::new("MyAssembly"),
[AssemblyBuilderAccess]::Run)
$mb = $ab.DefineDynamicModule("MyModule")
$tb = $mb.DefineType(
"MyClass",
[TypeAttributes]::Public,
$null,
[type[]]@([IProperty]))

$getAttr = $tb.DefineMethod(
"get_Id",
[MethodAttributes]"Public, Static, HideBySig, SpecialName",
[int],
[type]::EmptyTypes)
$getAttrIl = $getAttr.GetILGenerator()
$getAttrIl.Emit([OpCodes]::Ldc_I4_1)
$getAttrIL.Emit([OpCodes]::Ret)

$pb = $tb.DefineProperty(
"Id",
[PropertyAttributes]::None,
[int],
$null)
$pb.SetGetMethod($getAttr)

$null = $tb.CreateType()

[MyClass]::Id
It's failing with
Exception calling "CreateType" with "0" argument(s): "Virtual static method 'get_Id' is not implemented on type 'MyClass' from assembly 'MyAssembly, Version=0.0.0.0,Culture=neutral, PublicKeyToken=null'."
Looking at the IL code in sharplab.io for the equivalent C# code doesn't have anything jumping out at me https://sharplab.io/#v2:C4LglgNgPgAgzAAjAO2AUwE4DMCGBjNBASQAUMB7AB02AE8BYAKAG8mF2EYBGANgRwBGAZ2AZ8wJKmIATBMwQBzNMADcCAL5NNjJvE4AmBAGEAygAscGSmSo1aCEMRvUMdJq0YdOibnxQSiWXklCQBeAD4ELjVtdSA==. When adding the MethodAttributes.Virtual to the get_Id method builder it fails saying methods can't be static and virtual. Am I just missing something simple or is there something else I need to do here?
SharpLab
C#/VB/F# compiler playground.
11 Replies
Jimmacle
Jimmacle11mo ago
jerrywhat there a reason you chose this particular method of masochism? i've never seen someone try to dynamically generate C# from powershell
jborean
jboreanOP11mo ago
It's how PowerShell defines classes internally and for me to add support for this in normal pwsh classes in the PowerShell engine I need to know how to do it I was missing the following
$tb.DefineMethodOverride($getAttr, [IProperty].GetMethod("get_Id"))
$tb.DefineMethodOverride($getAttr, [IProperty].GetMethod("get_Id"))
Yawnder
Yawnder11mo ago
There might be something about that in C# 11, but before that, you sure can't mix inheritance with static. It means that having both virtual and static on the same member can't be right.
jborean
jboreanOP11mo ago
Isn't that what an abstract static method/property on interfaces can do, it ensure you set that on the implementing type?
Yawnder
Yawnder11mo ago
If you're in C#11 you could, but are you?
jborean
jboreanOP11mo ago
Yes
Unknown User
Unknown User11mo ago
Message Not Public
Sign In & Join Server To View
jborean
jboreanOP11mo ago
I don’t control how pwsh does things, I just need to fix it and this was asking how to do thing in the way that pwsh works. Ultimately it was DefineMethodOverride that was needed
Jimmacle
Jimmacle11mo ago
i would assume a lot of assemblies powershell uses are written in some .NET language and not actually in powershell but i'm not a powershell user so idk
jborean
jboreanOP11mo ago
This is part of powershell itself not a powershell module
jborean
jboreanOP11mo ago
It supports defining classes through a PowerShell syntax at runtime https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_classes?view=powershell-7.4 and uses TypeBuilder to do so. It just doesn’t currently support implementing an interface with a static abstract/virtual member hence me trying to figure out how to do so using TypeBuilder
about Classes - PowerShell
Describes how you can use classes to create your own custom types.
Want results from more Discord servers?
Add your server