1212using ServiceStack . Text . Json ;
1313using System . Globalization ;
1414using System . Reflection . Emit ;
15+
1516#if NETSTANDARD1_3
1617using System . Collections . Specialized ;
18+ using System . Net ;
19+ using System . Linq . Expressions ;
20+ using System . Runtime . Serialization ;
1721#endif
1822
1923namespace ServiceStack
@@ -74,7 +78,7 @@ public override bool FileExists(string filePath)
7478 return File . Exists ( filePath ) ;
7579 }
7680
77- public override bool DirectoryExists ( string dirPath )
81+ public override bool DirectoryExists ( string dirPath )
7882 {
7983 return Directory . Exists ( dirPath ) ;
8084 }
@@ -112,23 +116,22 @@ public override string MapAbsolutePath(string relativePath, string appendPartial
112116
113117 // Escape the assembly bin directory to the hostname directory
114118 var hostDirectoryPath = appendPartialPathModifier != null
115- ? assemblyDirectoryPath + appendPartialPathModifier
116- : assemblyDirectoryPath ;
119+ ? assemblyDirectoryPath + appendPartialPathModifier
120+ : assemblyDirectoryPath ;
117121
118122 return Path . GetFullPath ( relativePath . Replace ( "~" , hostDirectoryPath ) ) ;
119123 }
120124 return relativePath ;
121125 }
126+
122127#elif NETSTANDARD1_1
123128 public string BinPath = null ;
124129
125130 public override string MapAbsolutePath ( string relativePath , string appendPartialPathModifier )
126131 {
127132 if ( BinPath == null )
128133 {
129- var dll = typeof ( PclExport ) . GetAssembly ( ) ;
130- var pi = dll . GetType ( ) . GetProperty ( "CodeBase" ) ;
131- var codeBase = pi ? . GetProperty ( dll ) . ToString ( ) ;
134+ var codeBase = GetAssemblyCodeBase ( typeof ( PclExport ) . GetTypeInfo ( ) . Assembly ) ;
132135 if ( codeBase == null )
133136 throw new Exception ( "NetStandardPclExport.BinPath must be initialized" ) ;
134137
@@ -140,32 +143,256 @@ public override string MapAbsolutePath(string relativePath, string appendPartial
140143 : relativePath ;
141144 }
142145#endif
143-
144146 public static PclExport Configure ( )
145147 {
146148 Configure ( Provider ) ;
147149 return Provider ;
148150 }
149151
152+ public override string GetEnvironmentVariable ( string name )
153+ {
154+ #if NETSTANDARD1_3
155+ return Environment . GetEnvironmentVariable ( name ) ;
156+ #else
157+ return null ;
158+ #endif
159+ }
160+
150161 public override void WriteLine ( string line )
151162 {
163+ #if NETSTANDARD1_3
164+ Console . WriteLine ( line ) ;
165+ #else
152166 System . Diagnostics . Debug . WriteLine ( line ) ;
167+ #endif
153168 }
154169
155170 public override void WriteLine ( string format , params object [ ] args )
156171 {
172+ #if NETSTANDARD1_3
173+ Console . WriteLine ( format , args ) ;
174+ #else
157175 System . Diagnostics . Debug . WriteLine ( format , args ) ;
176+ #endif
177+ }
178+
179+ #if NETSTANDARD1_3
180+ public override void AddCompression ( WebRequest webReq )
181+ {
182+ var httpReq = ( HttpWebRequest ) webReq ;
183+ //TODO: Restore when AutomaticDecompression added to WebRequest
184+ //httpReq.Headers[HttpRequestHeader.AcceptEncoding] = "gzip,deflate";
185+ //httpReq.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
158186 }
159187
188+ public override void AddHeader ( WebRequest webReq , string name , string value )
189+ {
190+ webReq . Headers [ name ] = value ;
191+ }
192+ #endif
193+
160194 public override Assembly [ ] GetAllAssemblies ( )
161195 {
162196 return new Assembly [ 0 ] ;
163197 }
164198
165199 public override string GetAssemblyCodeBase ( Assembly assembly )
166200 {
167- return assembly . GetName ( ) . FullName ;
201+ var dll = typeof ( PclExport ) . GetAssembly ( ) ;
202+ var pi = dll . GetType ( ) . GetProperty ( "CodeBase" ) ;
203+ var codeBase = pi ? . GetProperty ( dll ) . ToString ( ) ;
204+ return codeBase ;
205+ }
206+
207+ #if NETSTANDARD1_3
208+ public override string GetAssemblyPath ( Type source )
209+ {
210+ var codeBase = GetAssemblyCodeBase ( source . GetTypeInfo ( ) . Assembly ) ;
211+ if ( codeBase == null )
212+ return null ;
213+
214+ var assemblyUri = new Uri ( codeBase ) ;
215+ return assemblyUri . LocalPath ;
216+ }
217+
218+ public override string GetAsciiString ( byte [ ] bytes , int index , int count )
219+ {
220+ return System . Text . Encoding . ASCII . GetString ( bytes , index , count ) ;
221+ }
222+
223+ public override byte [ ] GetAsciiBytes ( string str )
224+ {
225+ return System . Text . Encoding . ASCII . GetBytes ( str ) ;
226+ }
227+ #endif
228+
229+ public override bool InSameAssembly ( Type t1 , Type t2 )
230+ {
231+ return t1 . GetAssembly ( ) == t2 . GetAssembly ( ) ;
232+ }
233+
234+ public override Type GetGenericCollectionType ( Type type )
235+ {
236+ return type . GetTypeInfo ( ) . ImplementedInterfaces . FirstOrDefault ( t =>
237+ t . IsGenericType ( )
238+ && t . GetGenericTypeDefinition ( ) == typeof ( ICollection < > ) ) ;
239+ }
240+
241+ #if NETSTANDARD1_3
242+
243+ public override PropertySetterDelegate GetPropertySetterFn ( PropertyInfo propertyInfo )
244+ {
245+ var propertySetMethod = propertyInfo . SetMethod ( ) ;
246+ if ( propertySetMethod == null ) return null ;
247+
248+ if ( ! SupportsExpression )
249+ {
250+ return ( o , convertedValue ) =>
251+ propertySetMethod . Invoke ( o , new [ ] { convertedValue } ) ;
252+ }
253+
254+ try
255+ {
256+ var instance = Expression . Parameter ( typeof ( object ) , "i" ) ;
257+ var argument = Expression . Parameter ( typeof ( object ) , "a" ) ;
258+
259+ var instanceParam = Expression . Convert ( instance , propertyInfo . ReflectedType ( ) ) ;
260+ var valueParam = Expression . Convert ( argument , propertyInfo . PropertyType ) ;
261+
262+ var setterCall = Expression . Call ( instanceParam , propertySetMethod , valueParam ) ;
263+
264+ return Expression . Lambda < PropertySetterDelegate > ( setterCall , instance , argument ) . Compile ( ) ;
265+ }
266+ catch //fallback for Android
267+ {
268+ return ( o , convertedValue ) =>
269+ propertySetMethod . Invoke ( o , new [ ] { convertedValue } ) ;
270+ }
271+ }
272+
273+ public override PropertyGetterDelegate GetPropertyGetterFn ( PropertyInfo propertyInfo )
274+ {
275+ if ( ! SupportsExpression )
276+ return base . GetPropertyGetterFn ( propertyInfo ) ;
277+
278+ var getMethodInfo = propertyInfo . GetMethodInfo ( ) ;
279+ if ( getMethodInfo == null ) return null ;
280+ try
281+ {
282+ var oInstanceParam = Expression . Parameter ( typeof ( object ) , "oInstanceParam" ) ;
283+ var instanceParam = Expression . Convert ( oInstanceParam , propertyInfo . ReflectedType ( ) ) ; //propertyInfo.DeclaringType doesn't work on Proxy types
284+
285+ var exprCallPropertyGetFn = Expression . Call ( instanceParam , getMethodInfo ) ;
286+ var oExprCallPropertyGetFn = Expression . Convert ( exprCallPropertyGetFn , typeof ( object ) ) ;
287+
288+ var propertyGetFn = Expression . Lambda < PropertyGetterDelegate >
289+ (
290+ oExprCallPropertyGetFn ,
291+ oInstanceParam
292+ ) . Compile ( ) ;
293+
294+ return propertyGetFn ;
295+
296+ }
297+ catch ( Exception ex )
298+ {
299+ Tracer . Instance . WriteError ( ex ) ;
300+ throw ;
301+ }
302+ }
303+
304+ private static readonly MethodInfo setFieldMethod =
305+ typeof ( NetStandardPclExport ) . GetStaticMethod ( "SetField" ) ;
306+
307+ internal static void SetField < TValue > ( ref TValue field , TValue newValue )
308+ {
309+ field = newValue ;
310+ }
311+
312+ public override PropertySetterDelegate GetFieldSetterFn ( FieldInfo fieldInfo )
313+ {
314+ if ( ! SupportsExpression )
315+ return base . GetFieldSetterFn ( fieldInfo ) ;
316+
317+ var fieldDeclaringType = fieldInfo . DeclaringType ;
318+
319+ var sourceParameter = Expression . Parameter ( typeof ( object ) , "source" ) ;
320+ var valueParameter = Expression . Parameter ( typeof ( object ) , "value" ) ;
321+
322+ var sourceExpression = this . GetCastOrConvertExpression ( sourceParameter , fieldDeclaringType ) ;
323+
324+ var fieldExpression = Expression . Field ( sourceExpression , fieldInfo ) ;
325+
326+ var valueExpression = this . GetCastOrConvertExpression ( valueParameter , fieldExpression . Type ) ;
327+
328+ var genericSetFieldMethodInfo = setFieldMethod . MakeGenericMethod ( fieldExpression . Type ) ;
329+
330+ var setFieldMethodCallExpression = Expression . Call (
331+ null , genericSetFieldMethodInfo , fieldExpression , valueExpression ) ;
332+
333+ var setterFn = Expression . Lambda < PropertySetterDelegate > (
334+ setFieldMethodCallExpression , sourceParameter , valueParameter ) . Compile ( ) ;
335+
336+ return setterFn ;
337+ }
338+
339+ public override PropertyGetterDelegate GetFieldGetterFn ( FieldInfo fieldInfo )
340+ {
341+ if ( ! SupportsExpression )
342+ return base . GetFieldGetterFn ( fieldInfo ) ;
343+
344+ try
345+ {
346+ var fieldDeclaringType = fieldInfo . DeclaringType ;
347+
348+ var oInstanceParam = Expression . Parameter ( typeof ( object ) , "source" ) ;
349+ var instanceParam = this . GetCastOrConvertExpression ( oInstanceParam , fieldDeclaringType ) ;
350+
351+ var exprCallFieldGetFn = Expression . Field ( instanceParam , fieldInfo ) ;
352+ //var oExprCallFieldGetFn = this.GetCastOrConvertExpression(exprCallFieldGetFn, typeof(object));
353+ var oExprCallFieldGetFn = Expression . Convert ( exprCallFieldGetFn , typeof ( object ) ) ;
354+
355+ var fieldGetterFn = Expression . Lambda < PropertyGetterDelegate >
356+ (
357+ oExprCallFieldGetFn ,
358+ oInstanceParam
359+ )
360+ . Compile ( ) ;
361+
362+ return fieldGetterFn ;
363+ }
364+ catch ( Exception ex )
365+ {
366+ Tracer . Instance . WriteError ( ex ) ;
367+ throw ;
368+ }
369+ }
370+
371+ private Expression GetCastOrConvertExpression ( Expression expression , Type targetType )
372+ {
373+ Expression result ;
374+ var expressionType = expression . Type ;
375+
376+ if ( targetType . IsAssignableFromType ( expressionType ) )
377+ {
378+ result = expression ;
379+ }
380+ else
381+ {
382+ // Check if we can use the as operator for casting or if we must use the convert method
383+ if ( targetType . IsValueType ( ) && ! targetType . IsNullableType ( ) )
384+ {
385+ result = Expression . Convert ( expression , targetType ) ;
386+ }
387+ else
388+ {
389+ result = Expression . TypeAs ( expression , targetType ) ;
390+ }
391+ }
392+
393+ return result ;
168394 }
395+ #endif
169396
170397 public override string ToXsdDateTimeString ( DateTime dateTime )
171398 {
@@ -233,6 +460,46 @@ public override ParseStringDelegate GetJsReaderParseMethod<TSerializer>(Type typ
233460 return null ;
234461 }
235462
463+ #if NETSTANDARD1_3
464+ public override void InitHttpWebRequest ( HttpWebRequest httpReq ,
465+ long ? contentLength = null , bool allowAutoRedirect = true , bool keepAlive = true )
466+ {
467+ httpReq . Headers [ HttpRequestHeader . UserAgent ] = Env . ServerUserAgent ;
468+ //httpReq.AllowAutoRedirect = allowAutoRedirect;
469+ //httpReq.KeepAlive = keepAlive;
470+
471+ if ( contentLength != null )
472+ {
473+ httpReq . Headers [ HttpRequestHeader . ContentLength ] = contentLength . Value . ToString ( ) ;
474+ }
475+ }
476+
477+ public override void Config ( HttpWebRequest req ,
478+ bool ? allowAutoRedirect = null ,
479+ TimeSpan ? timeout = null ,
480+ TimeSpan ? readWriteTimeout = null ,
481+ string userAgent = null ,
482+ bool ? preAuthenticate = null )
483+ {
484+ //req.MaximumResponseHeadersLength = int.MaxValue; //throws "The message length limit was exceeded" exception
485+ //if (allowAutoRedirect.HasValue) req.AllowAutoRedirect = allowAutoRedirect.Value;
486+ //if (readWriteTimeout.HasValue) req.ReadWriteTimeout = (int)readWriteTimeout.Value.TotalMilliseconds;
487+ //if (timeout.HasValue) req.Timeout = (int)timeout.Value.TotalMilliseconds;
488+ if ( userAgent != null ) req . Headers [ HttpRequestHeader . UserAgent ] = userAgent ;
489+ //if (preAuthenticate.HasValue) req.PreAuthenticate = preAuthenticate.Value;
490+ }
491+
492+ public override string GetStackTrace ( )
493+ {
494+ return Environment . StackTrace ;
495+ }
496+ #endif
497+
498+ public override void CloseStream ( Stream stream )
499+ {
500+ stream . Close ( ) ;
501+ }
502+
236503 public static void InitForAot ( )
237504 {
238505 }
0 commit comments