diff --git a/SwiftMetaModelGenerator/DeclarationCollector.swift b/SwiftMetaModelGenerator/DeclarationCollector.swift
index 94c760f35ccb5c32be58fe94ca7a5ceb45da71b5..b320b112ad5e6a3919b3484764f7d2313c7acaeb 100644
--- a/SwiftMetaModelGenerator/DeclarationCollector.swift
+++ b/SwiftMetaModelGenerator/DeclarationCollector.swift
@@ -8,20 +8,51 @@
 import Foundation
 import SwiftSyntax
 
-struct ClassDeclaration {
+class ClassDeclaration {
     let name: String
-    let variables: [String]
+    let parents: [String]
+    
+    let variables: [Variable]
+    var needsMethodOverride: Bool
+    
+    init(name: String, parents: [String], variables: [Variable]) {
+        self.name = name
+        self.parents = parents
+        self.variables = variables
+        self.needsMethodOverride = false
+    }
+}
+
+class Variable {
+    let name: String
+    let type: String?
+    let optional: Bool?
+    let constant: Bool
+    let privateVisibility: Bool
+    let staticModifier: Bool
+    let hasAccessor: Bool
+    
+    init(name: String, type: String?, optional: Bool?, constant: Bool, privateVisibility: Bool, staticModifier: Bool, hasAccessor: Bool) {
+        self.name = name
+        self.type = type
+        self.optional = optional
+        self.constant = constant
+        self.privateVisibility = privateVisibility
+        self.staticModifier = staticModifier
+        self.hasAccessor = hasAccessor
+    }
 }
 
 class DeclarationCollector: SyntaxVisitor {
     
     private(set) var classes: [ClassDeclaration] = []
-    private var currentVariables: [String] = []
+    private var currentVariables: [Variable] = []
     
     override func visitPost(_ node: ClassDeclSyntax) {
         let name = node.identifier.text.trimmingCharacters(in: .whitespacesAndNewlines)
+        let inherences = node.inheritanceClause?.inheritedTypeCollection.map({ $0.typeName.description.trimmingCharacters(in: .whitespacesAndNewlines) }) ?? []
         
-        classes.append(ClassDeclaration(name: name, variables: currentVariables))
+        classes.append(ClassDeclaration(name: name, parents: inherences, variables: currentVariables))
         currentVariables = []
     }
     
@@ -29,7 +60,18 @@ class DeclarationCollector: SyntaxVisitor {
         for child: PatternBindingSyntax in node.bindings {
             if let parent = child.context as? VariableDeclSyntax, parent.context is ClassDeclSyntax {
                 let name = child.pattern.description.trimmingCharacters(in: .whitespacesAndNewlines)
-                currentVariables.append(name)
+                let type = child.typeAnnotation?.type.description.trimmingCharacters(in: .whitespacesAndNewlines)
+                let constant = parent.letOrVarKeyword.text.trimmingCharacters(in: .whitespacesAndNewlines) == "let"
+                
+                let privateVisibility = parent.modifiers?.map({ $0.name.text }).contains("private") ?? false
+                let staticModifier = parent.modifiers?.map({ $0.name.text }).contains("static") ?? false
+                let hasAccessor = child.accessor != nil
+                
+                if type == nil {
+                    print("Fail to observe type for \(name)")
+                }
+                
+                currentVariables.append(Variable(name: name, type: type?.replacingOccurrences(of: "?", with: ""), optional: type?.hasSuffix("?") , constant: constant, privateVisibility: privateVisibility, staticModifier: staticModifier, hasAccessor: hasAccessor))
             }
         }
         return .skipChildren
diff --git a/SwiftMetaModelGenerator/main.swift b/SwiftMetaModelGenerator/main.swift
index 1b842cd58687868f2c06eceef9e71720f9d2a1d4..70007e72e15eb69d5800c19bcc26a14e67378dfd 100644
--- a/SwiftMetaModelGenerator/main.swift
+++ b/SwiftMetaModelGenerator/main.swift
@@ -30,6 +30,12 @@ struct SwiftMetaModelGenerator: ParsableCommand
         } else {
             classes = try processFile(file: inputPath)
         }
+
+        for clazz in classes {
+            if clazz.parents.contains(where: { classes.map(\.name).contains($0) }) {
+                clazz.needsMethodOverride = true
+            }
+        }
         
         let context = [
           "classes": classes
diff --git a/SwiftMetaModelGenerator/templates/meta_model.stencil b/SwiftMetaModelGenerator/templates/meta_model.stencil
index 6fd4078b97dfc895a17c50c86848ed25e271f056..347277d16fa2bacc6b5e363dc9612b070ef3eff6 100644
--- a/SwiftMetaModelGenerator/templates/meta_model.stencil
+++ b/SwiftMetaModelGenerator/templates/meta_model.stencil
@@ -8,10 +8,29 @@ import Foundation
 // swiftlint:disable attributes file_length vertical_whitespace_closing_braces
 // swiftlint:disable identifier_name line_length type_body_length
 {% for class in classes %}
-class {{class.name}}_ {
+class {{class.name}}_ 
+{
 {% for variable in class.variables %}
-    static let {{ variable }}: String = "{{ variable }}"
+    static let {{ variable.name }}: String = "{{ variable.name }}"
 {% endfor %}
 }
+
+extension {{class.name}} 
+{
+    @objc {% if class.needsMethodOverride %} override {% endif %} func setValueByKey(key: String, value: Any?)
+    {
+        switch key {
+        {% for variable in class.variables %}
+        {% if not variable.constant and not variable.privateVisibility and not variable.staticModifier and not variable.hasAccessor %}
+        case "{{variable.name}}":
+            self.{{ variable.name }} = value {% if variable.optional %} as? {% else %} as! {% endif %} {{ variable.type }}
+        {% endif %}
+        {% endfor %}
+        default:
+            fatalError("Cannot set value for key \(key)")
+        }
+    }
+}
+
 {% endfor %}
 // swiftlint:enable identifier_name line_length type_body_length