Is it possible classes that derive from an abstract base class cannot be used in WF4? I have a library that define several object classes... I'm able to access objects in that library just fine except for objects that inherit from an abstract class.
Each time I reference the abstract class or any other classes in its inheritance chain, I get the following error:
"Compiler error(s) encountered processing expression "cust.DisplayName". 'cust' is not declared. It may be inaccessible due to its protection level."
In this case 'cust' is an instance of a CustomerAccount class which inherits from an AccountEntity (abstract) class which in turn inherits from a BaseEntity (abstract) class...
I can do the following in a C# console application and it works just fine:
CustomerAccount cust = new CustomerAccount();
cust.DisplayName = "John Doh";
Console.WriteLine("Out Put: " + ((iSvrBaseEntity)cust).DisplayName);
Console.WriteLine("Entity Type: " + cust.entityType);
But in the WF4 designer, I'm allowed to instantiate Cust and I'm allowed to assign another object to cust... but when I try to access a property in cust (or assign a value to one of it's properties, the error occurs.
Has anyone encountered this? Is it by design that WF4 doesn't deal with such inheritance? Is there a workaround?...
Thanks!
Types used need to be public but other than that any normal .NET type should work just fine.
Related
I need to dynamically load classes at runtime in Kotlin. I would like to check that they implement my interface, and if so, all green. Unfortunately, Kotlin's "smart casts" is failing me:
var className = "some.class.Name"
val unsafeClass = Class.forName(className).kotlin
require(unsafeClass.isSubclassOf(MyInterface::class)) {
"Class '$className' is not a MyInterface"
}
val safeClass = unsafeClass as KClass<MyInterface>
^^^^^^^^^^^^^^^^^^^^^^
Unchecked cast: KClass<out Any!> to KClass<MyInterface>
I'm clearly checking that the class implements the given interface. Can I re-phrase this code to avoid the warning?
I tried to test with is KClass<MyInterface> but I get a type erasure error (obviously, because the generic type information disappears at runtime.)
Edit: to clarify, my application needs to read class names "some.class.Name" at startup, during configuration; load those classes; check that they satisfy an interface; and store a Class or KClass reference for later. During runtime, it will use those references to create objects, using cls.createInstance() or such.
My question: is there any way to do so without getting unsafe cast warnings?
I can either get a warning at configuration time, when I cast the KClass<*> to KClass<MyInterface> (even though I required the class to be a subclass) but then I get no warning later on, because .createInstance() on a KClass<MyInterface> class reference returns a type-checked MyInterface instance.
Or, I can store the references as KClass<*>, without warnings at configuration time, but then I'll get the warning in the place where I create the instances, because I'll need to unsafe cast Object instances to MyInterface.
Is there any solution that will satisfy the compiler?
JVM and Kotlin implement generics only at the compiler level. One cannot see generic parameters of a generic class at runtime.
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
At runtime, there is no difference between Class<*> and Class<MyInterface>. These two are the same instance of Class type.
The warning that you have means that you have no information in the generic parameter at runtime, a compiler cannot validate it too, and it only can trust you
I do not see the reason cast the KClass to the KClass<MyInterface>. It is only necessary for an object, not it's class. Also, it probably can be simplified to use Class<*> instead, e.g:
val className = "some.class.Name"
val unsafeClass = Class.forName(className)
require(MyInterface::class.java.isAssignableFrom(unsafeClass)) {
"Class '$className' is not a MyInterface"
}
val safe = unsafeClass.newInstance() as MyInterface
This cast is not only unchecked, it's actually incorrect: because AMyInterfaceImpl::class has type KClass<AMyInterfaceImpl> and KClass is not covariant (for good reason), it does not have the type KClass<MyInterface>. You can see that from this code not compiling:
class AMyInterfaceImpl : MyInterface { ... }
val cls: KClass<MyInterface> = AMyInterfaceImpl::class
So if the cast could be checked, it would fail.
KClass<out MyInterface> would be correct, but I don't think the compiler will understand this and allow smart cast. It's just too rarely useful to teach the compiler.
Given the following classes
abstract class SomeAbstractClass { abstract val name: String }
data class DataClass( override val name: String ) : SomeAbstractClass()
class NoDataClass( override val name: String ) : SomeAbstractClass()
For any instance of SomeAbstractClass, can I determine whether it is a data class without relying on type checking?
Some background: this seemed the best way of combining inheritance and data classes to me, as suggested in a different answer. Now, within the initializer block of SomeAbstractClass, I want to throw an exception in case the derived type is not a data class to ensure 'correct' (immutable) implementations of derived types.
Using reflection, the Kotlin class description (KClass) can be obtained using the ::class syntax on the instance you want to investigate (in your case, this::class in the initializer block of the abstract class). This gives you access to isData:
true if this class is a data class.
However, as Oliver points out, data classes can still contain var members, so you likely also want to check whether all member variables (and their member variables recursively) are defined as val to ensure immutability of all deriving classes.
I want to do special functionality if I encounter a Kotlin class as compared to a generic Java class. How can I detect if it is a Kotlin class?
I was hoping that calling someClass.kotlin would throw an exception or fail if the class wasn't Kotlin. But it wraps Java classes just fine. Then I noticed that if I do someClass.kotlin.primaryConstructor it seems to be null for all java classes even if they have a default constructor, is that a good marker? But can that return null for a Kotlin class as well?
What is the best way to say "is this a Kotlin class?"
Kotlin adds an annotation to all of its classes, and you can safely check for its existence by name. This is an implementation detail and could change over time, but some key libraries use this annotation so it is likely to be ok indefinitely.
fun Class<*>.isKotlinClass(): Boolean {
return this.declaredAnnotations.any {
it.annotationClass.qualifiedName == "kotlin.Metadata"
}
}
Can be used as:
someClass.isKotlinClass()
The class kotlin.Metadata is not accessed directly because it is marked internal in the Kotlin runtime.
While the other answer may work (possibly outdated), many reflection features will not work on file classes or generated classes (lambdas, etc).
However, there is a parameter in the #Metadata annotation that can tell you if the class is what you are looking for:
A kind of the metadata this annotation encodes. Kotlin compiler recognizes the following kinds (see KotlinClassHeader.Kind):
1 Class
2 File
3 Synthetic class
4 Multi-file class facade
5 Multi-file class part
The class file with a kind not listed here is treated as a non-Kotlin file.
#get:JvmName("k")
val kind: Int = 1
We can take advantage of this to make sure we are only getting real classes:
val Class<*>.isKotlinClass get() = getAnnotation(Metadata::class.java)?.kind == 1
I can confirm this works in 1.6.20
I'm running into an interesting issue when using OCMock 3 when partially mocking an object that defines class methods. I'm not sure if this is an issue with the dynamic subclassing that takes part as partial mocking or my misunderstanding of the objc runtime. Any help would be greatly appreciated.
As part of running tests and other debug builds we do some runtime verification of method declarations using OmniFoundations' OBRuntimeCheck. One of these checks, in short, attempts to use the runtime to verify that type signatures match for class methods across inheritance and protocol conformance. This happens by listing the classes registered in the runtime and for each class the instance methods of the metaClass are copied. For each Method from the metaClass if it exists on the metaClass's superclass the type signatures are compared.
The problem comes when calling class_getInstanceMethod on the metaClass's superclass for one of the ocmock replacement selectors, ocmock_replaced_*. The test crashes EXC_BAD_INSTRUCTION code=EXC_i386_INVOP subcode=0x0 and no class for metaclass is logged in the console. Example given:
class_getInstanceMethod(metaSuperClass, NSSelectorFromString(#"ocmock_replaced_classMessage"))
When partial mocking an object that defines a class method, it appears that the OCMock 3 framework generates a dynamic subclass, does some isa swizzling of the mocked object and also some isa swizzling of the dynamically generated class' metaClass.
This behavior and crash is new in OCMock 3 and I'm really at a loss of where to look next. Any runtime gurus have any idea what may be going on here? When looking through the code it did surprise me that the dynamically generated class used for the mock was having it's meta class swizzled out, but I don't necessarily think that is wrong. For ease in debugging I have created a simplified test case in a fresh fork of OCMock. The crashing test can be found here. Any help for guidance would be greatly appreciated.
I may be way off here, but I thought the superclass of a metaClass is NSObject (which is why you can normally call NSObject instance methods on class objects). I'm not sure you should be doing anything, normally, with the superclass of a metaClass.
In general, the metaClass stores all of the information about class methods. Therefore, getting an "instance" method on a metaClass is the same as getting a class method on the associated regular Class. The runtime can simply dereference the "isa" pointer of an instance to find a method list to find instance methods; doing the same on a Class object gets the meta class (of the same structure) and therefore the same process results in finding the class methods.
OCMock will create a magic subclass for any partial mock, and change the class on that instance to the new subclass, so all the instance method swizzling will be specific to that instance. For class methods though, I thought it had to modify the original class itself -- otherwise, calls to the regular class method in regular code would not be intercepted. It keeps a copy of the original implementation so that when you call -stopMocking on the mock it can restore the original implementation (the added ocmock_replaced* impl will still be there but should no longer be called).
You could simply ignore any selector which starts with "ocmock_replaced" since that really is not related to your actual code you are presumably checking. You might also have better luck changing "class_getInstanceMethod(metaSuperClass, ..." to "class_getClassMethod(regularSuperClass, ..."). I'm not sure why you would be getting a crash though -- I would expect class_getInstanceMethod(metaSuperClass, ...) to just return NULL in most situations.
I have a class that inherits from JsonConverter:
JsonDataBagCreationConverter<T> : JsonConverter where T : IDataBag
I have a class Company that implements IDataBag
When I deserialize a single property of Company JsonDataBagCreationConverter has its ReadJson method invoked as I expect.
When I deserialize an array of Company, JsonDataBagCreationConverter has its ReadJson method invoked as I expect.
It also works for generic lists of Company.
But for certain containers of Company json.net will not recognize that the contents of the list is of type Company. So JsonDataBagCreationConverter is not used when I deserialize.
ie containers of type
System.Collections.DictionaryEntry,
System.Collections.ArrayList,
System.Collections.Hashtable,
System.Collections.SortedList
that stores Company objects.
I know that these containers are non-generic.
Is it possible to make the (de-)serializer look at the contents of these containers and use the JsonDataBagCreationConverter when the contents is Idatabag (ie a company)?
Best regards
Jan
Remove the where T : IDataBag from the converter and override CanConvert and write your logic to check your type there and accordly return true or false.