Swift discover protocol methods - reflection

I'm developing a HTML5 showcase application and I need to discover all the methods in my Swift protocols. All the protocols extends from a base protocol.
The application is a HTML5 showcase for testing this methods. The app calls the method and gives the response.
I found some information about one specific protocol but i need to discover all the protocols in my app and then all the information (name, arguments name arguments type and return values) about this methods.
#objc protocol Protocol {
func method1()
func method2() -> Bool
func method3(param1:Int) -> Bool
func method4(param1:Int, param2:Int, param3:Int) -> Bool
}
var numMethods:UInt32 = 0
var methods:UnsafeMutablePointer<objc_method_description> = protocol_copyMethodDescriptionList(Protocol.self, true, true, &numMethods)
for var iuint:CUnsignedInt = 0; iuint < numMethods; iuint++ {
var i:Int = Int(iuint)
var method:objc_method_description = methods[i]
println("Method #\(i): \(method.name)")
}
I'm using Objective-C Runtime Reference
Any ideas how to do this in swift?

You are going to want to get:
the method implementation (method_getImplementation) https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/c/func/method_getImplementation
and the method selector (method_getName) https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/c/func/method_getName
Then in objective-c (using a bridged file, of course), cast the method implementation (i.e. IMP) as a function pointer. Then call the function pointer in objective-c with the
target
selector
and any parameters you may have
id (*func)(id, SEL, id) = (void *)imp;
return func(target, selector, param);`
Take a look at how in this blog post he calls the init method and that should help as well.
http://ijoshsmith.com/2014/06/05/instantiating-classes-by-name-in-swift/

There is no real reflection in swift.
For more reading, please read:
Does Swift support reflection?
How do I print the type or class of a variable in Swift?
http://waffletower.blogspot.sg/2014/06/swift-doesnt-have-much-objective-c.html
https://github.com/mikeash/MAObjCRuntime

Related

Blazor Unmarshalled JavaScript interop

To improve performance in Blazor JS Interop calls, synchronous and unmarshalled apis are available
I struggle to find more information regarding the unmarshalled.
For example:
//javascript
JSFunctions.f1 = function (fields) {
var f1 = Blazor.platform.readStringField(fields, 0);
var f2 = Blazor.platform.readStringField(fields, 4);
var f3 = Blazor.platform.readStringField(fields, 8);
};
//F#
[<Inject>]
member val Js: IJSRuntime
let js = this.Js :?> IJSUnmarshalledRuntime
js.InvokeUnmarshalled<ElementReference, string, unit>("JSFunctions.f1", er, txt)
Where are the functions Blazor.platform.* defined?
Which one should be used to retrieve an argument of type ElementReference?
What is the second int parameter of the function readStringField and how should it be used?
Blazor object is a JavaScript object in global namespace (window) which added by blazor.webassembly.js in Blazor WebAssembly or blazor.server.js in Blazor Server. It added at the default template of Blazor Apps at the end of index.html (or _Host.cshtml) by following script:
<script autostart="false" src="_framework/blazor.webassembly.js"></script>
The Blazor object provide Blazor.platform and some useful api for example start() for manual start of Blazor.
This script also add another object named BINDING to global namespace (window.BINDING or simply BINDING).
They provide methods for working with .NET objects directly from JavaScript in unmarshalled way. for example you can read different type of data using
Blazor.platform.read....
You can read objects like ElementReference type object using:
Blazor.platform.readObjectField(fields,index)
Here fields is the input (struct or class) passed to JS function when you invoke it and index is its field offset in struct/class definition. You can read more about field offset in Microsoft documentations here.
Here is some example:
[StructLayout(LayoutKind.Explicit)]
public struct InteropStruct
{
[FieldOffset(0)]
public string Name;
[FieldOffset(8)]
public int Year;
}
You can also return a .Net object directly from JavaScript functions using BINDING as below:
return BINDING.js_string_to_mono_string(`Hello, ${name} (${year})!`);
You can discover more about these two objects in your browser developer tool for example by writing Blazor.platform. or BINDING.:

Internal Types for .NET Plugin Loading

I'm developing a plugin-loading system for my F# .NET 5 app, following this Microsoft guide. I wanted to provide an interface ICore that would have some internal, opaque state type that I would provide an interface for manipulating.
In Scala, I might do this like
trait ICore {
type State
def reset: State
}
and then call this method like
def resetCoreState(c: Core): c.State = c.reset
and implement a core like
object StringCore extends ICore {
override type State = String
override def reset: String = ""
}
however F# doesn't have this feature.
How should I design my interface,
type ICore() =
interface
// abstract type State
abstract method reset : State
end
let resetCoreState : ???
type StringCore() = ???
so that plugins can manage their own state?
I don't think there's any simple way to make the state type opaque, but here's how I would define these types in F#:
type ICore<'state> =
abstract member Reset : 'state
type StringCore() =
interface ICore<string> with
member __.Reset = ""
let resetCoreState (core : ICore<_>) =
core.Reset

Flutter : Use generics for http response

I am new in Flutter.
I migrate from android development by Kotlin to Flutter.
I would like to get a response from Http Url.
All of the server's responses are in one format and the type of 2 variables is generic.
I did it in Kotlin by this 2 class.
class BaseResponse<T> {
#SerializedName("IsSuccess")
var isSuccess: Boolean = false
#SerializedName("Item")
var item: T? = null
#SerializedName("ListItems")
var listItems: List<T>? = null
#SerializedName("ErrorCode")
var errorCode: Int? = null
And other classes and responses are like this:
data class TablesModel(var id: Long, var tableType: String, var tableCost: Int, var banner: String?, var onLineCount: Int)
And my responses are like this :
BaseResponse<TablesModel>
Now I would like to do it in Flutter. Please help me.
For general json models in Dart is very common to use ValueObjects/Mojos.
You could use json_serializer and a builder to prepare the model classes yourself. Or a tool like
https://app.quicktype.io/ that will generate the model from you from a json response.
Regarding generics, the proper way is to have an abstract model class and implement the different responses types in subclasses, or you can leverage the Type system passing a argument so the compiler knows how to treat those properties.
The simplest approach would be to use the type dynamic or Object like jsonDecode doest, but you lose type checks for errors at compile time and autocomplete hints from the IDE.

Javascript dict vs {}

When using a {} as follows:
var m = {};
Then m is an Object that does not possess the methods of a Dict. You can see by pasting into jsfiddle
var m = {};
m['a'] = 'x';
alert(m.keys());
This will not run - since keys() is not a method on the given object. So then - how to get a dictionary with all its methods?
Update From #SLaks suggestion: Changing the original line to
var m = new Map();
does the trick
There is no such thing as a dictionary in Javascript.
You can use a regular object as a dictionary, as you're doing, and use methods like Object.keys() to help you.
If you use ES6 (or a polyfill), you can use the Map class, which is a normal class with get() and set() methods.
{} is an "object literal". It has no methods or properties other than what's part of the object prototype (a limited set of functions, such as toString, hasOwnProperty, etc), and what you define on it. It is otherwise empty and does not expose functionality you'd expect on a Dictionary. That's where Object comes in.
The static Object reference has an API on it that you can provide your objects to and effectively exposes a set of functions that can be performed on your object as if they were default methods a "dictionary" might expose.
var m = {};
m.a = 'x';
Object.keys(m) // => ['a']
You can find more methods that Object supports on MDN, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
There is no "Dictionary", but an object in JavaScript can be used in a very similar way to a Map in Java.
var myObject = {}
...
for (var key in myObject) {
if (myObject.hasOwnProperty(key)) {
var value = myObject[key];
}
}
The hasOwnProperty() check is to avoid finding keys higher up JavaScripts prototype chain.

How can I let Rebus determine an endpoint for an interface and not for an implementation of that interface

When I Send an instance created by AutoMapper.Mapper.DynamicMap() I run into an error where Rebus seems to want to determine an endpoint for proxy type returned by DynamicMap. This instance will contain an implementation of T assuming T is an interface type.
Is there a way in which I can let Rebus determine an endpoint for the interface type T and not for the implementing type returned by DynamicMap()?
I tried playing around with IDetermineMessageOwnership but had no luck so far.
public static void Send<T>(this IBus bus, object source)
{
var message = Mapper.DynamicMap<T>(source);
bus.Send<T>(message);
}
Thanks in advance!
Sure! In your case, you could create your own implementation of IDetermineMessageOwnership which is the service that Rebus uses to map a message type to an endpoint.
If you want to leverage Rebus' existing logic, you could decorate any chosen strategy and extend it with a keep-looking-at-all-implemented-interfaces-until-one-can-be-mapped strategy like so:
Configure.With(adapter)
.(...)
.MessageOwnership(o => o.FromRebusConfigurationSection())
.Decorators(d => d.AddDecoration(DecorateOwnershipMapping)))
.CreateBus()
.Start();
where DecorateOwnershipMapping would install a decorator on top of whatever is configured like so:
void DecorateOwnershipMapping(ConfigurationBackbone b)
{
b.DetermineMessageOwnership = new CustomizedEndpointMapper(b.DetermineMessageOwnership);
}
and a possible implementation could look like this:
class CustomizedEndpointMapper : IDetermineMessageOwnership
{
readonly IDetermineMessageOwnership wrappedEndpointMapper;
public CustomizedEndpointMapper(IDetermineMessageOwnership wrappedEndpointMapper)
{
this.wrappedEndpointMapper = wrappedEndpointMapper;
}
public string GetEndpointFor(Type messageType)
{
var mappingCandidates = new[] {messageType}
.Concat(messageType.GetInterfaces())
.ToList();
foreach (var typeToTry in mappingCandidates)
{
try
{
return wrappedEndpointMapper.GetEndpointFor(typeToTry);
}
catch{}
}
throw new InvalidOperationException(string.Format("Could not determine the owner of message of type {0} - attempted to map the following types: {1}",
messageType, string.Join(", ", mappingCandidates)));
}
}
thus iterating through the concrete type as well as all inherited interface types when trying to determine the owning endpoint.
In your case, I believe this would work flawlessly when determining the message owner. Only problem is that the serializer will most likely complain, because the dynamically generated type cannot be recognized again when the message is received.
Hence, this trick requires customization of the serializer as well. If you're using the (default) JSON serializer, you might get away with some custom resolvers like so:
Configure.With(...)
.(...)
.Serialization(s => s.UseJsonSerializer()
.AddNameResolver(CustomNameResolver)
.AddTypeResolver(CustomTypeResolver))
.(...)
where CustomNameResolver and CustomTypeResolver are methods that must then take care of mapping the type to a type name and mapping the type name to a type that can then be deserialized into. In order to make this work with AutoMapper, you'll probably need to either
a) somehow use AutoMapper to look up the type of the received message and return that type from CustomTypeResolver, or
b) customize the serializer to have AutoMapper somehow participate in generating the object to be returned
but I must admit that I'm unsure whether the last part will play out smoothly.
A final note: if you succeed in making this work, I suggest you pack up your configuration spells into a reusable extension method on RebusConfigurer so that your endpoints can just go
Configure.With(...)
.(...)
.UseMyFunkyAutoMapperMessagesJustTheWayILikeIt()
.CreateBus().Start();
in all your Rebus endpoints...
I'll appreciate it if you'll let me know how this works out for you! :)

Resources