77using  System . Collections . Generic ; 
88using  System . ComponentModel ; 
99using  System . Diagnostics ; 
10+ using  System . Diagnostics . CodeAnalysis ; 
1011using  System . IO ; 
1112#if ! NET 
1213using  System . Linq ; 
2526#pragma warning disable CA1031  // Do not catch general exception types 
2627#pragma warning disable S2333  // Redundant modifiers should not be used 
2728#pragma warning disable S3011  // Reflection should not be used to increase accessibility of classes, methods, or fields 
28- #pragma warning disable SA1202  // Public members should come before private members 
2929
3030namespace  Microsoft . Extensions . AI ; 
3131
@@ -373,15 +373,16 @@ public static AIFunction Create(MethodInfo method, object? target, string? name
373373    } 
374374
375375    /// <summary> 
376-     /// Creates an <see cref="AIFunction"/> instance for a method, specified via a  <see cref="MethodInfo"/> for 
377-     /// an  instance method and  a <see cref="Func{AIFunctionArguments,Object} "/> for constructing an instance of  
378-     /// the receiver object  each time the <see cref="AIFunction"/>  is invoked. 
376+     /// Creates an <see cref="AIFunction"/> instance for a method, specified via an  <see cref="MethodInfo"/> for 
377+     /// and  instance method, along with  a <see cref="Type "/> representing the type of the target object to  
378+     /// instantiate  each time the method  is invoked. 
379379    /// </summary> 
380380    /// <param name="method">The instance method to be represented via the created <see cref="AIFunction"/>.</param> 
381-     /// <param name="createInstanceFunc"> 
382-     /// Callback used on each function invocation to create an instance of the type on which the instance method <paramref name="method"/> 
383-     /// will be invoked. If the returned instance is <see cref="IAsyncDisposable"/> or <see cref="IDisposable"/>, it will be disposed of 
384-     /// after <paramref name="method"/> completes its invocation. 
381+     /// <param name="targetType"> 
382+     /// The <see cref="Type"/> to construct an instance of on which to invoke <paramref name="method"/> when 
383+     /// the resulting <see cref="AIFunction"/> is invoked. <see cref="Activator.CreateInstance(Type)"/> is used, 
384+     /// utilizing the type's public parameterless constructor. If an instance can't be constructed, an exception is 
385+     /// thrown during the function's invocation. 
385386    /// </param> 
386387    /// <param name="options">Metadata to use to override defaults inferred from <paramref name="method"/>.</param> 
387388    /// <returns>The created <see cref="AIFunction"/> for invoking <paramref name="method"/>.</returns> 
@@ -455,16 +456,22 @@ public static AIFunction Create(MethodInfo method, object? target, string? name
455456    /// </para> 
456457    /// </remarks> 
457458    /// <exception cref="ArgumentNullException"><paramref name="method"/> is <see langword="null"/>.</exception> 
458-     /// <exception cref="ArgumentNullException"><paramref name="createInstanceFunc "/> is <see langword="null"/>.</exception> 
459+     /// <exception cref="ArgumentNullException"><paramref name="targetType "/> is <see langword="null"/>.</exception> 
459460    /// <exception cref="ArgumentException"><paramref name="method"/> represents a static method.</exception> 
460461    /// <exception cref="ArgumentException"><paramref name="method"/> represents an open generic method.</exception> 
461462    /// <exception cref="ArgumentException"><paramref name="method"/> contains a parameter without a parameter name.</exception> 
463+     /// <exception cref="ArgumentException"><paramref name="targetType"/> is not assignable to <paramref name="method"/>'s declaring type.</exception> 
462464    /// <exception cref="JsonException">A parameter to <paramref name="method"/> or its return type is not serializable.</exception> 
463465    public  static   AIFunction  Create ( 
464466        MethodInfo  method , 
465-         Func < AIFunctionArguments ,  object >  createInstanceFunc , 
466-         AIFunctionFactoryOptions ?  options  =  null )  => 
467-         ReflectionAIFunction . Build ( method ,  createInstanceFunc ,  options  ??  _defaultOptions ) ; 
467+         [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ]  Type  targetType , 
468+         AIFunctionFactoryOptions ?  options  =  null ) 
469+     { 
470+         _  =  Throw . IfNull ( method ) ; 
471+         _  =  Throw . IfNull ( targetType ) ; 
472+ 
473+         return  ReflectionAIFunction . Build ( method ,  targetType ,  options  ??  _defaultOptions ) ; 
474+     } 
468475
469476    private  sealed  class  ReflectionAIFunction  :  AIFunction 
470477    { 
@@ -495,11 +502,10 @@ public static ReflectionAIFunction Build(MethodInfo method, object? target, AIFu
495502
496503        public  static   ReflectionAIFunction  Build ( 
497504            MethodInfo  method , 
498-             Func < AIFunctionArguments ,   object >   createInstanceFunc , 
505+             [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ]   Type   targetType , 
499506            AIFunctionFactoryOptions  options ) 
500507        { 
501508            _  =  Throw . IfNull ( method ) ; 
502-             _  =  Throw . IfNull ( createInstanceFunc ) ; 
503509
504510            if  ( method . ContainsGenericParameters ) 
505511            { 
@@ -511,7 +517,13 @@ public static ReflectionAIFunction Build(
511517                Throw . ArgumentException ( nameof ( method ) ,  "The method must be an instance method." ) ; 
512518            } 
513519
514-             return  new ( ReflectionAIFunctionDescriptor . GetOrCreate ( method ,  options ) ,  createInstanceFunc ,  options ) ; 
520+             if  ( method . DeclaringType  is  {  }  declaringType  && 
521+                 ! declaringType . IsAssignableFrom ( targetType ) ) 
522+             { 
523+                 Throw . ArgumentException ( nameof ( targetType ) ,  "The target type must be assignable to the method's declaring type." ) ; 
524+             } 
525+ 
526+             return  new ( ReflectionAIFunctionDescriptor . GetOrCreate ( method ,  options ) ,  targetType ,  options ) ; 
515527        } 
516528
517529        private  ReflectionAIFunction ( ReflectionAIFunctionDescriptor  functionDescriptor ,  object ?  target ,  AIFunctionFactoryOptions  options ) 
@@ -523,17 +535,20 @@ private ReflectionAIFunction(ReflectionAIFunctionDescriptor functionDescriptor,
523535
524536        private  ReflectionAIFunction ( 
525537            ReflectionAIFunctionDescriptor  functionDescriptor , 
526-             Func < AIFunctionArguments ,   object >   createInstanceFunc , 
538+             [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ]   Type   targetType , 
527539            AIFunctionFactoryOptions  options ) 
528540        { 
529541            FunctionDescriptor  =  functionDescriptor ; 
530-             CreateInstanceFunc  =  createInstanceFunc ; 
542+             TargetType  =  targetType ; 
543+             CreateInstance  =  options . CreateInstance ; 
531544            AdditionalProperties  =  options . AdditionalProperties  ??  EmptyReadOnlyDictionary < string ,  object ? > . Instance ; 
532545        } 
533546
534547        public  ReflectionAIFunctionDescriptor  FunctionDescriptor  {  get ;  } 
535548        public  object ?  Target  {  get ;  } 
536-         public  Func < AIFunctionArguments ,  object > ?  CreateInstanceFunc  {  get ;  } 
549+         [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ] 
550+         public  Type ?  TargetType  {  get ;  } 
551+         public  Func < Type ,  AIFunctionArguments ,  object > ?  CreateInstance  {  get ;  } 
537552
538553        public  override  IReadOnlyDictionary < string ,  object ? >  AdditionalProperties  {  get ;  } 
539554        public  override  string  Name  =>  FunctionDescriptor . Name ; 
@@ -550,12 +565,14 @@ private ReflectionAIFunction(
550565            object ?  target  =  Target ; 
551566            try 
552567            { 
553-                 if  ( CreateInstanceFunc  is  {  }  func ) 
568+                 if  ( TargetType  is  {  }  targetType ) 
554569                { 
555570                    Debug . Assert ( target  is  null ,  "Expected target to be null when we have a non-null target type" ) ; 
556571                    Debug . Assert ( ! FunctionDescriptor . Method . IsStatic ,  "Expected an instance method" ) ; 
557572
558-                     target  =  func ( arguments ) ; 
573+                     target  =  CreateInstance  is  not null  ? 
574+                         CreateInstance ( targetType ,  arguments )  : 
575+                         Activator . CreateInstance ( targetType ) ; 
559576                    if  ( target  is  null ) 
560577                    { 
561578                        Throw . InvalidOperationException ( "Unable to create an instance of the target type." ) ; 
@@ -1088,34 +1105,6 @@ public override void Flush()
10881105        { 
10891106        } 
10901107
1091-         public  override  Task  FlushAsync ( CancellationToken  cancellationToken )  => 
1092-             Task . CompletedTask ; 
1093- 
1094-         public  override  Task  WriteAsync ( byte [ ]  buffer ,  int  offset ,  int  count ,  CancellationToken  cancellationToken )  => 
1095-             WriteAsync ( new  ReadOnlyMemory < byte > ( buffer ,  offset ,  count ) ,  cancellationToken ) . AsTask ( ) ; 
1096- 
1097- #if NET 
1098-         public  override 
1099- #else
1100-         private 
1101- #endif
1102-         ValueTask  WriteAsync ( ReadOnlyMemory < byte >  buffer ,  CancellationToken  cancellationToken  =  default ) 
1103-         { 
1104-             EnsureNotDisposed ( ) ; 
1105- 
1106-             if  ( cancellationToken . IsCancellationRequested ) 
1107-             { 
1108-                 return  new  ValueTask ( Task . FromCanceled ( cancellationToken ) ) ; 
1109-             } 
1110- 
1111-             EnsureCapacity ( _position  +  buffer . Length ) ; 
1112- 
1113-             buffer . Span . CopyTo ( _buffer . AsSpan ( _position ) ) ; 
1114-             _position  +=  buffer . Length ; 
1115- 
1116-             return  default ; 
1117-         } 
1118- 
11191108        public  override  int  Read ( byte [ ]  buffer ,  int  offset ,  int  count )  =>  throw  new  NotSupportedException ( ) ; 
11201109        public  override  long  Seek ( long  offset ,  SeekOrigin  origin )  =>  throw  new  NotSupportedException ( ) ; 
11211110        public  override  void  SetLength ( long  value )  =>  throw  new  NotSupportedException ( ) ; 
0 commit comments