@@ -249,21 +249,40 @@ private static TypeInfo BuildSymbolicEnumType(
249249 return enumBuilder . CreateTypeInfo ( ) ! ;
250250 }
251251
252- private static TypeAttributes GetTypeAttributes ( TypeKind typeKind )
252+ private static TypeAttributes GetTypeAttributes ( ITypeSymbol typeSymbol )
253253 {
254254 TypeAttributes attributes = TypeAttributes . Public ;
255- if ( typeKind == TypeKind . Interface )
256- {
257- attributes |= TypeAttributes . Interface ;
258- }
259- else if ( typeKind == TypeKind . Delegate )
260- {
261- attributes |= TypeAttributes . Sealed ;
262- }
263- if ( typeKind != TypeKind . Enum )
255+
256+ switch ( typeSymbol . TypeKind )
264257 {
265- attributes |= TypeAttributes . Abstract ;
258+ case TypeKind . Interface :
259+ attributes |= TypeAttributes . Interface | TypeAttributes . Abstract ;
260+ break ;
261+
262+ case TypeKind . Class :
263+ if ( typeSymbol . IsAbstract || typeSymbol . IsStatic )
264+ {
265+ attributes |= TypeAttributes . Abstract ;
266+ }
267+ if ( typeSymbol . IsSealed || typeSymbol . IsStatic )
268+ {
269+ attributes |= TypeAttributes . Sealed ;
270+ }
271+ break ;
272+
273+ case TypeKind . Struct :
274+ attributes |= TypeAttributes . Sealed | TypeAttributes . BeforeFieldInit ;
275+ break ;
276+
277+ case TypeKind . Delegate :
278+ attributes |= TypeAttributes . Sealed ;
279+ break ;
280+
281+ case TypeKind . Enum :
282+ attributes |= TypeAttributes . Abstract ;
283+ break ;
266284 }
285+
267286 return attributes ;
268287 }
269288
@@ -291,7 +310,7 @@ private static Type BuildSymbolicObjectType(
291310 {
292311 typeBuilder = ModuleBuilder . DefineType (
293312 name : typeFullName ,
294- GetTypeAttributes ( typeSymbol . TypeKind ) ,
313+ GetTypeAttributes ( typeSymbol ) ,
295314 parent : baseType ) ;
296315
297316 if ( typeSymbol . TypeParameters . Length > 0 )
@@ -347,7 +366,15 @@ static PropertyInfo GetAttributeProperty(Type type, string name)
347366 return thisType ;
348367 }
349368
350- return typeBuilder . CreateTypeInfo ( ) ! ;
369+ try
370+ {
371+ return typeBuilder . CreateTypeInfo ( ) ! ;
372+ }
373+ catch ( Exception ex )
374+ {
375+ throw new InvalidOperationException (
376+ $ "Failed to create type info for type: { typeSymbol . Name } ", ex ) ;
377+ }
351378 }
352379
353380 /// <summary>
@@ -390,7 +417,15 @@ static void BuildType(
390417 if ( SymbolicTypes . TryGetValue ( typeFullName , out Type ? type ) &&
391418 type is TypeBuilder typeBuilder )
392419 {
393- typeBuilder . CreateTypeInfo ( ) ;
420+ try
421+ {
422+ typeBuilder . CreateTypeInfo ( ) ;
423+ }
424+ catch ( Exception ex )
425+ {
426+ throw new InvalidOperationException (
427+ $ "Failed to create type info for type: { typeSymbol . Name } ", ex ) ;
428+ }
394429 }
395430 }
396431
@@ -449,7 +484,10 @@ private static void BuildSymbolicTypeMembers(
449484 }
450485
451486 foreach ( ISymbol memberSymbol in typeSymbol . GetMembers ( )
452- . Where ( ( m ) => m . DeclaredAccessibility == Accessibility . Public ) )
487+ . Where ( ( m ) => m . DeclaredAccessibility == Accessibility . Public ||
488+ ( m . DeclaredAccessibility == Accessibility . Private &&
489+ ( m is IMethodSymbol ms && ms . ExplicitInterfaceImplementations . Length > 0 ) ||
490+ ( m is IPropertySymbol ps && ps . ExplicitInterfaceImplementations . Length > 0 ) ) ) )
453491 {
454492 if ( memberSymbol is IMethodSymbol constructorSymbol &&
455493 constructorSymbol . MethodKind == MethodKind . Constructor )
@@ -458,6 +496,7 @@ private static void BuildSymbolicTypeMembers(
458496 }
459497 else if ( memberSymbol is IMethodSymbol methodSymbol &&
460498 ( methodSymbol . MethodKind == MethodKind . Ordinary ||
499+ methodSymbol . MethodKind == MethodKind . ExplicitInterfaceImplementation ||
461500 methodSymbol . MethodKind == MethodKind . DelegateInvoke ) )
462501 {
463502 BuildSymbolicMethod ( typeBuilder , methodSymbol , genericTypeParameters ) ;
@@ -476,7 +515,7 @@ private static void BuildSymbolicTypeMembers(
476515 }
477516 else if ( memberSymbol is INamedTypeSymbol nestedTypeSymbol )
478517 {
479- TypeAttributes attributes = GetTypeAttributes ( nestedTypeSymbol . TypeKind ) ;
518+ TypeAttributes attributes = GetTypeAttributes ( nestedTypeSymbol ) ;
480519 attributes &= ~ TypeAttributes . Public ;
481520 attributes |= TypeAttributes . NestedPublic ;
482521
@@ -533,9 +572,17 @@ private static void BuildSymbolicMethod(
533572 Type [ ] ? genericTypeParameters )
534573 {
535574 bool isDelegateMethod = typeBuilder . BaseType == typeof ( MulticastDelegate ) ;
536- MethodAttributes attributes = MethodAttributes . Public | ( methodSymbol . IsStatic ?
537- MethodAttributes . Static : MethodAttributes . Virtual | ( isDelegateMethod ?
538- MethodAttributes . HideBySig : MethodAttributes . Abstract ) ) ;
575+ // All nonstatic methods are declared virtual on symbolic types.
576+ // This allows any struct/class methods to implement interface methods.
577+ MethodAttributes attributes =
578+ ( methodSymbol . DeclaredAccessibility == Accessibility . Public ?
579+ MethodAttributes . Public : MethodAttributes . Private ) |
580+ ( methodSymbol . IsStatic ? MethodAttributes . Static : MethodAttributes . Virtual ) |
581+ ( methodSymbol . IsAbstract ? MethodAttributes . Abstract : default ) |
582+ ( methodSymbol . ExplicitInterfaceImplementations . Length > 0 ?
583+ MethodAttributes . Final : default ) |
584+ ( isDelegateMethod ? MethodAttributes . HideBySig : default ) ;
585+
539586 MethodBuilder methodBuilder = typeBuilder . DefineMethod (
540587 methodSymbol . Name ,
541588 attributes ,
@@ -565,29 +612,41 @@ private static void BuildSymbolicMethod(
565612 methodBuilder . SetImplementationFlags (
566613 MethodImplAttributes . Runtime | MethodImplAttributes . Managed ) ;
567614 }
568- else if ( methodSymbol . IsStatic )
615+ else if ( ! methodSymbol . IsAbstract )
569616 {
570- // Static methods cannot be abstract; emit a minimal body.
617+ // Emit a minimal method body.
571618 methodBuilder . GetILGenerator ( ) . Emit ( OpCodes . Ret ) ;
572619 }
620+
621+ if ( methodSymbol . ExplicitInterfaceImplementations . Length > 0 )
622+ {
623+ MethodInfo interfaceMethod =
624+ methodSymbol . ExplicitInterfaceImplementations [ 0 ] . AsMethodInfo ( ) ;
625+ typeBuilder . DefineMethodOverride ( methodBuilder , interfaceMethod ) ;
626+ }
573627 }
574628
575629 private static void BuildSymbolicProperty (
576630 TypeBuilder typeBuilder ,
577631 IPropertySymbol propertySymbol ,
578632 Type [ ] ? genericTypeParameters )
579633 {
634+ MethodAttributes attributes = MethodAttributes . SpecialName |
635+ ( propertySymbol . DeclaredAccessibility == Accessibility . Public ?
636+ MethodAttributes . Public : MethodAttributes . Private ) |
637+ ( propertySymbol . IsStatic ? MethodAttributes . Static : MethodAttributes . Virtual ) |
638+ ( propertySymbol . IsAbstract ? MethodAttributes . Abstract : default ) |
639+ ( propertySymbol . IsVirtual ? MethodAttributes . Virtual : default ) |
640+ ( propertySymbol . ExplicitInterfaceImplementations . Length > 0 ?
641+ MethodAttributes . Final : default ) ;
642+
580643 PropertyBuilder propertyBuilder = typeBuilder . DefineProperty (
581644 propertySymbol . Name ,
582645 PropertyAttributes . None ,
583646 propertySymbol . Type . AsType ( genericTypeParameters , buildType : false ) ,
584647 propertySymbol . Parameters . Select (
585648 ( p ) => p . Type . AsType ( genericTypeParameters , buildType : false ) ) . ToArray ( ) ) ;
586649
587- MethodAttributes attributes = MethodAttributes . SpecialName | MethodAttributes . Public |
588- ( propertySymbol . IsStatic ? MethodAttributes . Static :
589- MethodAttributes . Abstract | MethodAttributes . Virtual ) ;
590-
591650 if ( propertySymbol . GetMethod != null )
592651 {
593652 MethodBuilder getMethodBuilder = typeBuilder . DefineMethod (
@@ -598,8 +657,15 @@ private static void BuildSymbolicProperty(
598657 propertySymbol . GetMethod . Parameters . Select (
599658 ( p ) => p . Type . AsType ( genericTypeParameters , buildType : false ) ) . ToArray ( ) ) ;
600659 BuildSymbolicParameters ( getMethodBuilder , propertySymbol . GetMethod . Parameters ) ;
601- if ( propertySymbol . IsStatic ) getMethodBuilder . GetILGenerator ( ) . Emit ( OpCodes . Ret ) ;
660+ if ( ! propertySymbol . IsAbstract ) getMethodBuilder . GetILGenerator ( ) . Emit ( OpCodes . Ret ) ;
602661 propertyBuilder . SetGetMethod ( getMethodBuilder ) ;
662+
663+ if ( propertySymbol . ExplicitInterfaceImplementations . Length > 0 )
664+ {
665+ MethodInfo interfaceGetMethod =
666+ propertySymbol . ExplicitInterfaceImplementations [ 0 ] . GetMethod ! . AsMethodInfo ( ) ;
667+ typeBuilder . DefineMethodOverride ( getMethodBuilder , interfaceGetMethod ) ;
668+ }
603669 }
604670
605671 if ( propertySymbol . SetMethod != null )
@@ -612,8 +678,15 @@ private static void BuildSymbolicProperty(
612678 propertySymbol . SetMethod . Parameters . Select (
613679 ( p ) => p . Type . AsType ( genericTypeParameters , buildType : false ) ) . ToArray ( ) ) ;
614680 BuildSymbolicParameters ( setMethodBuilder , propertySymbol . SetMethod . Parameters ) ;
615- if ( propertySymbol . IsStatic ) setMethodBuilder . GetILGenerator ( ) . Emit ( OpCodes . Ret ) ;
681+ if ( ! propertySymbol . IsAbstract ) setMethodBuilder . GetILGenerator ( ) . Emit ( OpCodes . Ret ) ;
616682 propertyBuilder . SetSetMethod ( setMethodBuilder ) ;
683+
684+ if ( propertySymbol . ExplicitInterfaceImplementations . Length > 0 )
685+ {
686+ MethodInfo interfaceSetMethod =
687+ propertySymbol . ExplicitInterfaceImplementations [ 0 ] . SetMethod ! . AsMethodInfo ( ) ;
688+ typeBuilder . DefineMethodOverride ( setMethodBuilder , interfaceSetMethod ) ;
689+ }
617690 }
618691 }
619692
0 commit comments